home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / progtool / c / egem_210 / egem / source / dial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-25  |  68.9 KB  |  3,187 lines

  1.  
  2. #include <time.h>
  3. #include <string.h>
  4. #include "proto.h"
  5.  
  6. #ifdef __MINT_LIB__
  7. #include <mintbind.h>
  8. #endif
  9.  
  10. #define DEFAULT_ERR        "[1][ Zu viele DEFAULT-Schalter! | Nur ein DEFAULT-Schalter | pro Baum möglich! ][ Ok ]"
  11. #define INDDEFAULT_ERR    "[1][ Zu viele INDDEFAULT-Objekte! | Nur ein INDDEFAULT-Objekt | pro Baum möglich! ][ Ok ]"
  12. #define HELP_ERR        "[1][ Zu viele HELP-Objekte! | Nur ein HELP-Objekt | pro Baum möglich! ][ Ok ]"
  13. #define UNDO_ERR        "[1][ Zu viele UNDO-Objekte! | Nur ein UNDO-Objekt | pro Baum möglich! ][ Ok ]"
  14.  
  15. #define CHKHOTKEY_ERR_A    "[1][ CHKHOTKEY-Fehler: | Das Text-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  16. #define CHKHOTKEY_ERR_B "[1][ CHKHOTKEY-Fehler: | Das HOTKEY-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  17. #define RBHOTKEY_ERR_A    "[1][ RBHOTKEY-Fehler: |  Das Text-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  18. #define RBHOTKEY_ERR_B    "[1][ RBHOTKEY-Fehler: | Das HOTKEY-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  19.  
  20. #define HOTKEY_ERR        "[1][ HOTKEY-Fehler: | doppelter HOTKEY '%c'! | (Objekt-Nummer %d) ][ Ok ]"
  21.  
  22. typedef struct _list
  23. {
  24.     X_TEXT            *start;
  25.     int             index;
  26.     struct _list    *next;
  27. } V_LIST;
  28.  
  29. const char __ident_e_gem[] = "$Id: EnhancedGEM v" E_GEM_VERSION " $";
  30.  
  31. int ap_id, multi, aes_version, winx, magx, mint, grhandle, x_handle;
  32. int gr_cw, gr_ch, gr_bw, gr_bh, gr_sw, gr_sh;
  33. int max_w, max_h, colors, colors_available, planes;
  34. int small_font, small_font_id, ibm_font, ibm_font_id, fonts_loaded = FAIL;
  35. int menu_available, search;
  36.  
  37. GRECT desk;
  38. VRECT clip;
  39. MFDB scr_mfdb;
  40. OBJECT *iconified;
  41. MFDB *screen = &scr_mfdb;
  42. int menu_id = -1;
  43.  
  44. OBJECT    *_menu;
  45.  
  46. WIN        _windows[MAX_WINDOWS+1];
  47. int     _opened,_ac_close,_min_timer,_last_top;
  48.  
  49. boolean _back_win,_nonsel_fly,_dial_round=TRUE;
  50. int        _bevent,_bottom,_ascii,_ascii_digit,_popup;
  51.  
  52. char    _cycle_hot='W',_close_hot='U';
  53. int        _cycle,_close,_alert_color=BLACK,_no_av_win;
  54.  
  55. DIAINFO    *_dia_list[MAX_DIALS+1];
  56. int        _dia_len;
  57.  
  58. int cdecl (*_icfs)(int,...);
  59.  
  60. static char *c_arrow[] = {"\x04","\x03","\x01","\x02"};
  61.  
  62. static int        *cycle_but,*box_on,*box_off,*radio_on,*radio_off;
  63. static int        *arrow_up,*arrow_up_sel,*arrow_down,*arrow_down_sel;
  64. static int        *arrow_left,*arrow_left_sel,*arrow_right,*arrow_right_sel;
  65. static int        mouse_flag,gr_dcw;
  66. static boolean    always_keys,toMouse,return_default=TRUE;
  67. static int        menu_inst,menu_test;
  68.  
  69. static X_TEXT    v_text[128];
  70. static V_LIST    v_list = {v_text,0,NULL};
  71.  
  72. static DIAINFO *win_list[MAX_DIALS+1];
  73. static int        win_len = 0, dial_pattern = 0,dial_color = BLACK;
  74. static int        image_w,image_h,big_img;
  75. static boolean    dial_tframe = TRUE,dial_tsmall = FALSE,dial_title = FALSE;
  76. static boolean  menu_nice = TRUE;
  77.  
  78. static int cdecl draw_fly(PARMBLK *);
  79. static int cdecl draw_text(PARMBLK *);
  80. static int cdecl draw_underline(PARMBLK *);
  81. static int cdecl draw_cyclebutton(PARMBLK *);
  82. static int cdecl draw_box(PARMBLK *);
  83. static int cdecl draw_radiobutton(PARMBLK *);
  84. static int cdecl draw_arrows(PARMBLK *);
  85. static int cdecl draw_menu(PARMBLK *);
  86.  
  87. static USERBLK    cycleblk = {draw_cyclebutton,1};
  88. static USERBLK    flyblk = {draw_fly,0};
  89. static USERBLK    hotkeyblk = {draw_underline,1};
  90. static USERBLK    checkblk = {draw_box,1};
  91. static USERBLK    rbuttblk = {draw_radiobutton,1};
  92. static USERBLK    unlnblk = {draw_underline,0x0101l};
  93. static USERBLK    arrows = {draw_arrows,1};
  94. static USERBLK  menublk = {draw_menu,0};
  95.  
  96. static boolean     open_flydialog(OBJECT *,DIAINFO *,boolean,boolean);
  97. static boolean    open_windialog(OBJECT *,DIAINFO *,char *,char *,OBJECT *,int,boolean,boolean);
  98.  
  99. static void        redraw_dialog(DIAINFO *,GRECT *,GRECT *);
  100.  
  101. static DIAINFO    *get_info(int *);
  102. static void     dial_center(OBJECT *,boolean,int,int);
  103. static void     dial_pos(OBJECT *,int,int);
  104. static void     find_fly(DIAINFO *);
  105. static void     test_inddefault(DIAINFO *);
  106.  
  107. static void     vdi_trans(int,int,void *);
  108. static void     scale_img(int *,int,int,int,int,int);
  109.  
  110. static void     mouse_cursor(DIAINFO *,XEVENT *);
  111. static int        klickobj(DIAINFO *,XEVENT *,int *,boolean);
  112. static int        key_handler(DIAINFO *,int,int,XEVENT *);
  113. static int        objekt_handler(DIAINFO *,int,int,int,int,boolean);
  114.  
  115. static int        is_rb_chk(OBJECT *,int);
  116.  
  117. static void     do_jump_fly(DIAINFO *,int,int);
  118.  
  119. static void     get_image(IMAGES *,int,BUTTON *,int **,int **);
  120. static void     set_images(IMAGES *,int **,int **);
  121.  
  122. static int        do_func(DIAINFO *,int,int,XEVENT *);
  123. static void     vrt_copy(int *,PARMBLK *,int,int);
  124.  
  125. void dial_options(boolean round,boolean t_frame,boolean t_small,boolean niceline,boolean ret,boolean back,boolean nonsel,boolean keys,boolean mouse)
  126. {
  127.     reg int old_back = _back_win;
  128.  
  129.     always_keys = keys;
  130.     _dial_round = round;
  131.     dial_tframe = t_frame;
  132.     dial_tsmall = t_small;
  133.     menu_nice = niceline;
  134.     return_default    = ret;
  135.     _nonsel_fly = nonsel;
  136.     toMouse = mouse;
  137.     _back_win = (back) ? 1 : 0;
  138.  
  139.     if (_back_win!=old_back && _bevent)
  140.     {
  141.         reg int i;
  142.         reg WIN *wins=_windows;
  143.  
  144.         for (i=MAX_WINDOWS;--i>=0;wins++)
  145.             if (wins->handle>0 && !(wins->iconified & ICFS))
  146.                 wind_set(wins->handle,WF_BEVENT,_back_win);
  147.     }
  148. }
  149.  
  150. void dial_colors(int d_pattern,int d_color,int popup,int hotkey,int check,int radio,int arrow,int alert)
  151. {
  152.     dial_color     = d_color;
  153.     dial_pattern = d_pattern;
  154.  
  155.     cycleblk.ub_parm = popup;
  156.     hotkeyblk.ub_parm = hotkey;
  157.     checkblk.ub_parm = check;
  158.     rbuttblk.ub_parm = radio;
  159.     arrows.ub_parm = arrow;
  160.     _alert_color = alert;
  161. }
  162.  
  163. void title_options(boolean title,int color,int size)
  164. {
  165.     dial_title    = title;
  166.     unlnblk.ub_parm = (size<<8)|color;
  167. }
  168.  
  169. static void get_image(IMAGES *img,int index,BUTTON *but,int **img_on,int **img_off)
  170. {
  171.     reg int *on = NULL,*off;
  172.  
  173.     if (index>=0 && index<img->count)
  174.     {
  175.         on    = img->image[index].hi_on;
  176.         off = img->image[index].hi_off;
  177.     }
  178.     else if (but)
  179.     {
  180.         on = but->but_on;
  181.         off = but->but_off;
  182.     }
  183.  
  184.     if (on)
  185.     {
  186.         *img_on = on;
  187.         if (img_off)
  188.             *img_off= off;
  189.     }
  190. }
  191.  
  192. void radio_image(int index,BUTTON *radio)
  193. {
  194.     get_image(&_radios,index,radio,&radio_on,&radio_off);
  195. }
  196.  
  197. void check_image(int index,BUTTON *check)
  198. {
  199.     get_image(&_checks,index,check,&box_on,&box_off);
  200. }
  201.  
  202. void arrow_image(int index,BUTTON *down,BUTTON *up,BUTTON *left,BUTTON *right)
  203. {
  204.     get_image(&_arrows_left,index,left,&arrow_left_sel,&arrow_left);
  205.     get_image(&_arrows_right,index,right,&arrow_right_sel,&arrow_right);
  206.     get_image(&_arrows_down,index,down,&arrow_down_sel,&arrow_down);
  207.     get_image(&_arrows_up,index,up,&arrow_up_sel,&arrow_up);
  208. }
  209.  
  210. void cycle_image(int index,BUTTON *cycle)
  211. {
  212.     get_image(&_cycles,index,cycle,&cycle_but,NULL);
  213. }
  214.  
  215. static boolean init_flag;
  216.  
  217. boolean init_gem(char *m_entry,char *x_name,char *a_name,int av_msgs,int va_msgs,int xacc_msgs)
  218. {
  219.     if (init_flag)
  220.         return(TRUE);
  221.     else if (x_name==NULL || a_name==NULL)
  222.         return (FALSE);
  223.  
  224.     AES_VERSION = 0;
  225.     if ((ap_id = appl_init())>=0 && (aes_version = AES_VERSION)>0)
  226.     {
  227.         X_ATTR xattr;
  228.         int dummy,info1,info2,work_out[57];
  229.  
  230.         wind_update(BEG_UPDATE);
  231.         grhandle = graf_handle(&gr_cw,&gr_ch,&gr_bw,&gr_bh);
  232.         gr_dcw = gr_cw<<1;
  233.  
  234.         if (open_work(&x_handle,work_out))
  235.         {
  236.             long value;
  237.  
  238.             multi = (GLOBAL[1]!=1);
  239.  
  240.             max_w = work_out[0]+1;
  241.             max_h = work_out[1]+1;
  242.             colors = work_out[13];
  243.             colors_available = work_out[39];
  244.  
  245.             vq_extnd(x_handle,1,work_out);
  246.             planes = work_out[4];
  247.  
  248.             if (get_cookie(COOKIE_MAGX,&value) && value!=0l)
  249.             {
  250.                 magx = ((int **) value)[2][24];
  251.                 if (magx<0x0200)
  252.                     magx = 0;
  253.             }
  254.  
  255.             if (get_cookie(COOKIE_MINT,&value))
  256.                 mint = (int) value;
  257.  
  258.         #ifndef __MINT_LIB__
  259.             Pdomain(1);
  260.         #endif
  261.  
  262.             _dd_available = ((Dsetdrv(Dgetdrv()) & (1l<<('U'-'A'))) && Fxattr(0,"U:\\PIPE",(void *) &xattr)==0);
  263.  
  264.             if (wind_xget(0,WF_RETURN,&dummy,&dummy,&dummy,&dummy)==0)
  265.             {
  266.                 int version;
  267.                 wind_xget(0,WF_WINX,&version,&dummy,&dummy,&dummy);
  268.                 winx = (version & 0x0fff);
  269.                 if (winx<0x0210)
  270.                     winx = 0;
  271.             }
  272.  
  273.             appl_xgetinfo(12,&info1,&dummy,&dummy,&dummy);
  274.             if ((info1 & 384)!=384)
  275.                 if (!get_cookie(COOKIE_ICFS,(long *) &_icfs) || _icfs==NULL)
  276.                     _icfs = _default_icfs;
  277.  
  278.             appl_xgetinfo(11,&info1,&dummy,&dummy,&dummy);
  279.             _bottom = (aes_version>=0x0331 || winx || (info1 & 64));
  280.             _bevent = (aes_version>=0x0331 || winx || (info1 & 32));
  281.             _min_timer = (aes_version>=0x0140) ? 0 : 1;
  282.  
  283.             appl_xgetinfo(6,&dummy,&dummy,&info1,&info2);
  284.             menu_available = (_app || magx);
  285.             menu_inst = (magx || info2);
  286.             menu_test = (aes_version>=0x0400 || info1);
  287.  
  288.             search = (aes_version>=0x0400 || magx || (appl_xgetinfo(4,&dummy,&dummy,&info1,&dummy) && info1>0));
  289.  
  290.             if (m_entry && m_entry[0] && (!_app || aes_version>=0x0400))
  291.             {
  292.                 menu_id = menu_register(ap_id,m_entry);
  293.                 if (_app)
  294.                     menu_id = -1;
  295.             }
  296.             else
  297.                 menu_id = -1;
  298.  
  299.             appl_getfontinfo(0,&ibm_font,&ibm_font_id,&dummy);
  300.             appl_getfontinfo(1,&small_font,&small_font_id,&dummy);
  301.  
  302.             vst_font(x_handle,small_font_id);
  303.             vst_height(x_handle,small_font,&dummy,&dummy,&gr_sw,&gr_sh);
  304.  
  305.             vs_attr();
  306.             v_set_text(ibm_font_id,ibm_font,BLACK,NULL);
  307.             vst_alignment(x_handle,0,5,&dummy,&dummy);
  308.  
  309.             v_set_mode(MD_REPLACE);
  310.             v_set_line(BLACK,1);
  311.             vsl_type(x_handle,1);
  312.             vsl_ends(x_handle,0,0);
  313.             vsl_udsty(x_handle,0x5555);
  314.  
  315.             v_set_fill(BLACK,1,1);
  316.             vsf_perimeter(x_handle,1);
  317.  
  318.             if (gr_cw<8 || gr_ch<8)
  319.             {
  320.                 image_w = min(gr_dcw,16);
  321.                 image_h = min(gr_ch,16);
  322.                 big_img = FAIL;
  323.             }
  324.             else if (gr_ch>15)
  325.             {
  326.                 image_w = image_h = 16;
  327.                 big_img = TRUE;
  328.             }
  329.             else
  330.             {
  331.                 image_w = 16;
  332.                 image_h = 8;
  333.                 big_img = FALSE;
  334.             }
  335.  
  336.             set_images(&_radios,&radio_on,&radio_off);
  337.             set_images(&_checks,&box_on,&box_off);
  338.             set_images(&_arrows_left,&arrow_left_sel,&arrow_left);
  339.             set_images(&_arrows_right,&arrow_right_sel,&arrow_right);
  340.             set_images(&_arrows_up,&arrow_up_sel,&arrow_up);
  341.             set_images(&_arrows_down,&arrow_down_sel,&arrow_down);
  342.             set_images(&_cycles,&cycle_but,NULL);
  343.  
  344.             wind_xget(0,WF_WORKXYWH,&desk.g_x,&desk.g_y,&desk.g_w,&desk.g_h);
  345.             rc_grect_to_array(&desk,(int *) &clip);
  346.             _clip_rect(&desk);
  347.  
  348.             _scrp_init();
  349.             MouseArrow();
  350.             if (aes_version>=0x0400 || (appl_xgetinfo(10,&info1,&dummy,&dummy,&dummy) && (info1 & 0xff)>=9))
  351.                 shel_write(9,0,0x01,NULL,NULL);
  352.  
  353.             _XAccSendStartup(x_name,a_name,av_msgs,va_msgs,xacc_msgs);
  354.  
  355.             wind_update(END_UPDATE);
  356.             init_flag = TRUE;
  357.             return(TRUE);
  358.         }
  359.         else
  360.         {
  361.             wind_update(END_UPDATE);
  362.             appl_exit();
  363.         }
  364.     }
  365.  
  366.     return(FALSE);
  367. }
  368.  
  369. #ifdef __PUREC__
  370. int wind_xget(int w_handle, int w_field, int *w1, int *w2, int *w3,int *w4)
  371. {
  372.     INTIN[0] = w_handle;
  373.     INTIN[1] = w_field;
  374.     _aes(0,0x68020500l);
  375.  
  376.     *w1 = INTOUT[1];
  377.     *w2 = INTOUT[2];
  378.     *w3 = INTOUT[3];
  379.     *w4 = INTOUT[4];
  380.  
  381.     return(INTOUT[0]);
  382. }
  383. #endif
  384.  
  385. int appl_getinfo(int ap_gtype,int *ap_gout1,int *ap_gout2,int *ap_gout3,int *ap_gout4)
  386. {
  387.     reg int *array;
  388.  
  389.     INTIN[0] = ap_gtype;
  390.     _aes(0,0x82010500L);
  391.  
  392.     array = &INTOUT[5];
  393.     *ap_gout4 = *--array;
  394.     *ap_gout3 = *--array;
  395.     *ap_gout2 = *--array;
  396.     *ap_gout1 = *--array;
  397.     return(*--array);
  398. }
  399.  
  400. static int has_agi = FAIL;
  401.  
  402. int appl_xgetinfo(int type,int *out1,int *out2,int *out3,int *out4)
  403. {
  404.     int back = 0;
  405.  
  406.     if (has_agi==FAIL)
  407.         has_agi = (aes_version>=0x400 || magx || winx || appl_find("?AGI")==0) ? TRUE : FALSE;
  408.  
  409.     if (has_agi)
  410.         back = appl_getinfo(type,out1,out2,out3,out4);
  411.  
  412.     if (back==0)
  413.         *out1 = *out2 = *out3 = *out4 = 0;
  414.  
  415.     return (back);
  416. }
  417.  
  418. int appl_getfontinfo(int ap_gtype,int *height,int *id,int *type)
  419. {
  420.     int dummy,attrib[10];
  421.  
  422.     vs_attr();
  423.  
  424.     if (appl_xgetinfo(ap_gtype,height,id,type,&dummy))
  425.     {
  426.         if (*id==-12124)
  427.             *id = 1;
  428.  
  429.         if (vst_font(x_handle,*id)!=*id && fonts_loaded<0 && vq_gdos())
  430.             fonts_loaded = vst_load_fonts(x_handle,0);
  431.  
  432.         return (TRUE);
  433.     }
  434.  
  435.     vqt_attributes(grhandle,attrib);
  436.     *id = attrib[0];
  437.  
  438.     if (vst_font(x_handle,*id)!=*id && fonts_loaded<0 && vq_gdos())
  439.         fonts_loaded = vst_load_fonts(x_handle,0);
  440.  
  441.     if (ap_gtype==1)
  442.     {
  443.         vst_font(x_handle,*id);
  444.         vst_point(x_handle,1,&dummy,&dummy,&dummy,&dummy);
  445.         vqt_attributes(x_handle,attrib);
  446.     }
  447.  
  448.     *height = attrib[7];
  449.     *type = 0;
  450.  
  451.     return(TRUE);
  452. }
  453.  
  454. void exit_gem(int result)
  455. {
  456.     if (init_flag)
  457.     {
  458.         if (_menu)
  459.             menu_install(_menu,FALSE);
  460.  
  461.         close_all_windows();
  462.         _XAccAvExit();
  463.  
  464.         if (fonts_loaded>=0)
  465.         {
  466.             vst_unload_fonts(x_handle,0);
  467.             fonts_loaded = FAIL;
  468.         }
  469.  
  470.         close_work(x_handle);
  471.         if (_app)
  472.             appl_exit();
  473.         else
  474.             evnt_timer(0,32000);
  475.     }
  476.  
  477.     exit (result);
  478. }
  479.  
  480. static void set_images(IMAGES *images,int **on,int **off)
  481. {
  482.     if (big_img!=FAIL)
  483.     {
  484.         reg IMAGE *im = images->image;
  485.         reg int i;
  486.  
  487.         for (i=0;i<images->count;i++,im++)
  488.         {
  489.             if (big_img==FALSE)
  490.             {
  491.                 if (im->lo_on!=NULL)
  492.                     im->hi_on = im->lo_on;
  493.                 if (im->lo_off!=NULL)
  494.                     im->hi_off = im->lo_off;
  495.  
  496.                 vdi_trans(image_w,image_h,im->hi_on);
  497.                 vdi_trans(image_w,image_h,im->hi_off);
  498.  
  499.                 if (im->lo_on==NULL)
  500.                     scale_img(im->hi_on,16,16,image_w,image_h,DARK_SCALING);
  501.                 if (im->lo_off==NULL)
  502.                     scale_img(im->hi_off,16,16,image_w,image_h,DARK_SCALING);
  503.             }
  504.             else
  505.             {
  506.                 vdi_trans(image_w,image_h,im->hi_on);
  507.                 vdi_trans(image_w,image_h,im->hi_off);
  508.             }
  509.         }
  510.  
  511.         if (images->count>0)
  512.         {
  513.             *on = images->image->hi_on;
  514.             if (off)
  515.                 *off = images->image->hi_off;
  516.         }
  517.     }
  518. }
  519.  
  520. #define scale_coords(x,y,ow,oh)    { x = (x*gr_cw)/ow; y = y*gr_ch/oh; }
  521.  
  522. void scale_image(OBJECT *obj,int scaling,int orig_cw,int orig_ch)
  523. {
  524.     reg unsigned char type = (unsigned char) obj->ob_type;
  525.  
  526.     if (type!=G_ICON && type!=G_IMAGE)
  527.         return;
  528.  
  529.     if (orig_cw<=1)
  530.         orig_cw = 8;
  531.  
  532.     if (orig_ch<=1)
  533.         orig_ch = 16;
  534.  
  535.     if (scaling & TEST_SCALING)
  536.     {
  537.         if (orig_cw==gr_cw && orig_ch==gr_ch)
  538.             return;
  539.         else
  540.             scaling |= SCALING;
  541.     }
  542.  
  543.     if (scaling & SCALING)
  544.     {
  545.         if (gr_cw>=orig_cw && gr_ch>=orig_ch)
  546.         {
  547.             obj->ob_x += (obj->ob_width-(obj->ob_width*orig_cw)/gr_cw)>>1;
  548.             obj->ob_y += (obj->ob_height-(obj->ob_height*orig_ch)/gr_ch)>>1;
  549.         }
  550.         else if (type==G_ICON)
  551.         {
  552.             ICONBLK *icn = obj->ob_spec.iconblk;
  553.  
  554.             if (icn->ib_hicon>3)
  555.             {
  556.                 reg int ow,oh,nw,nh;
  557.  
  558.                 ow = nw = icn->ib_wicon;
  559.                 oh = nh = icn->ib_hicon;
  560.  
  561.                 scale_coords(icn->ib_xicon,icn->ib_yicon,orig_cw,orig_ch);
  562.                 scale_coords(nw,nh,orig_cw,orig_ch);
  563.                 icn->ib_hicon = nh;
  564.                 scale_coords(icn->ib_xtext,icn->ib_ytext,orig_cw,orig_ch);
  565.                 scale_coords(icn->ib_xchar,icn->ib_ychar,orig_cw,orig_ch);
  566.  
  567.                 scale_img(icn->ib_pdata,ow,oh,nw,nh,scaling);
  568.                 scale_img(icn->ib_pmask,ow,oh,nw,nh,scaling);
  569.             }
  570.         }
  571.         else
  572.         {
  573.             BITBLK *blk = obj->ob_spec.bitblk;
  574.  
  575.             if (blk->bi_hl>3)
  576.             {
  577.                 reg int ow,oh,nw,nh;
  578.  
  579.                 ow = nw = blk->bi_wb<<3;
  580.                 oh = nh = blk->bi_hl;
  581.  
  582.                 scale_coords(nw,nh,orig_cw,orig_ch);
  583.                 blk->bi_hl = nh;
  584.                 scale_coords(blk->bi_x,blk->bi_y,orig_cw,orig_ch);
  585.  
  586.                 scale_img((int *) blk->bi_pdata,ow,oh,nw,nh,scaling);
  587.             }
  588.         }
  589.     }
  590. }
  591.  
  592. static void scale_img(int *source,int w,int h,int n_w, int n_h, int scaling)
  593. {
  594.     if (source!=NULL)
  595.     {
  596.         reg int pxy[8],dark = (scaling & DARK_SCALING),vr_mode = (dark) ? 7 : 3;
  597.         reg MFDB image;
  598.  
  599.         mfdb(&image,source,w,h,0,1);
  600.  
  601.         if (n_h<h)
  602.         {
  603.             reg int y,n_y,l_y,flag=TRUE;
  604.  
  605.             pxy[0] = pxy[4] = l_y = n_y = y = 0;
  606.             pxy[2] = pxy[6] = w-1;
  607.  
  608.             for (;y<h;y++)
  609.             {
  610.                 if (n_y>=h || dark || y==(h-1))
  611.                 {
  612.                     pxy[1] = pxy[3] = y;
  613.                     pxy[5] = pxy[7] = l_y;
  614.                     vro_cpyfm(x_handle,(flag) ? 3 : vr_mode,pxy,&image,&image);
  615.                     if (n_y>=h)
  616.                     {
  617.                         n_y -= h;
  618.                         l_y++;
  619.                         flag = TRUE;
  620.                     }
  621.                     else
  622.                         flag = FALSE;
  623.                 }
  624.                 n_y += n_h;
  625.             }
  626.  
  627.             for (y=n_h-1;y<h;y++)
  628.             {
  629.                 pxy[1] = pxy[3] = pxy[5] = pxy[7] = y;
  630.                 vro_cpyfm(x_handle,0,pxy,&image,&image);
  631.             }
  632.             h = n_h;
  633.         }
  634.  
  635.         if (n_w<w)
  636.         {
  637.             reg int x,n_x,l_x,flag = TRUE;
  638.  
  639.             pxy[1] = pxy[5] = l_x = n_x = x = 0;
  640.             pxy[3] = pxy[7] = h-1;
  641.  
  642.             for (;x<w;x++)
  643.             {
  644.                 if (n_x>=w || dark || x==(w-1))
  645.                 {
  646.                     pxy[0] = pxy[2] = x;
  647.                     pxy[4] = pxy[6] = l_x;
  648.                     vro_cpyfm(x_handle,(flag) ? 3 : vr_mode,pxy,&image,&image);
  649.                     if (n_x>=w)
  650.                     {
  651.                         n_x -= w;
  652.                         l_x++;
  653.                         flag = TRUE;
  654.                     }
  655.                     else
  656.                         flag = FALSE;
  657.                 }
  658.                 n_x += n_w;
  659.             }
  660.  
  661.             for (x=n_w-1;x<w;x++)
  662.             {
  663.                 pxy[0] = pxy[2] = pxy[4] = pxy[6] = x;
  664.                 vro_cpyfm(x_handle,0,pxy,&image,&image);
  665.             }
  666.         }
  667.     }
  668. }
  669.  
  670. static void vdi_trans(int w,int h,void *data)
  671. {
  672.     if (data)
  673.     {
  674.         reg MFDB src,dst;
  675.  
  676.         mfdb(&src,(int *) data,w,h,1,1);
  677.         mfdb(&dst,(int *) data,w,h,0,1);
  678.         vr_trnfm(x_handle,&src,&dst);
  679.     }
  680. }
  681.  
  682. void trans_image(OBJECT *obj)
  683. {
  684.     if ((unsigned char) obj->ob_type==G_ICON)
  685.     {
  686.         reg ICONBLK *icn=obj->ob_spec.iconblk;
  687.         vdi_trans(icn->ib_wicon,icn->ib_hicon,icn->ib_pmask);
  688.         vdi_trans(icn->ib_wicon,icn->ib_hicon,icn->ib_pdata);
  689.     }
  690.     else
  691.     {
  692.         reg BITBLK *img=obj->ob_spec.bitblk;
  693.         vdi_trans(img->bi_wb<<3,img->bi_hl,img->bi_pdata);
  694.     }
  695. }
  696.  
  697. static void vrt_copy(int *image,PARMBLK *pb,int color,int selected)
  698. {
  699.     reg MFDB src;
  700.     reg int pxy[8],col[2],off = (big_img==FAIL) ? 1:0;
  701.  
  702.     pxy[0] = pxy[1] = 0;
  703.     pxy[2] = image_w - 1;
  704.     pxy[3] = image_h - 1;
  705.     pxy[4] = pb->pb_x + (gr_cw-(image_w>>1)) + off;
  706.     pxy[5] = pb->pb_y + ((gr_ch-image_h)>>1) + off;
  707.     pxy[6] = pxy[4] + pxy[2];
  708.     pxy[7] = pxy[5] + pxy[3];
  709.  
  710.     if (selected)
  711.     {
  712.         col[1] = color;
  713.         col[0] = 0;
  714.     }
  715.     else
  716.     {
  717.         col[0] = color;
  718.         col[1] = 0;
  719.     }
  720.     mfdb(&src,image,16,image_h,0,1);
  721.     vrt_cpyfm(x_handle,1,pxy,&src,screen,col);
  722. }
  723.  
  724. void rsrc_calc(OBJECT *tree,int scaling,int orig_cw,int orig_ch)
  725. {
  726.     reg OBJECT *obj=tree;
  727.     reg int index=0,low_byte=0x00ff,scale=FALSE;
  728.     int rest_x,rest_y,rest_w,rest_h;
  729.  
  730.     if (orig_cw>1 && orig_ch>1)
  731.         if (orig_cw!=gr_cw || orig_ch!=gr_ch)
  732.         {
  733.             scale = TRUE;
  734.  
  735.             do
  736.             {
  737.                 obj++;
  738.  
  739.                 if (obj->ob_type==G_TITLE)
  740.                 {
  741.                     scale = FALSE;
  742.                     break;
  743.                 }
  744.             } while (!(obj->ob_flags & LASTOB));
  745.  
  746.             obj = tree;
  747.         }
  748.  
  749.     for (;;)
  750.     {
  751.         if (scale)
  752.         {
  753.             rest_x = *((signed char *) &obj->ob_x);
  754.             rest_y = *((signed char *) &obj->ob_y);
  755.             rest_w = *((signed char *) &obj->ob_width);
  756.             rest_h = *((signed char *) &obj->ob_height);
  757.  
  758.             obj->ob_x &= low_byte;
  759.             obj->ob_y &= low_byte;
  760.             obj->ob_width &= low_byte;
  761.             obj->ob_height &= low_byte;
  762.  
  763.             rsrc_obfix(tree,index++);
  764.  
  765.             if (rest_x)
  766.                 obj->ob_x += (rest_x*gr_cw)/orig_cw;
  767.             if (rest_y)
  768.                 obj->ob_y += (rest_y*gr_ch)/orig_ch;
  769.             if (rest_w)
  770.                 obj->ob_width += (rest_w*gr_cw)/orig_cw;
  771.             if (rest_h)
  772.                 obj->ob_height += (rest_h*gr_ch)/orig_ch;
  773.         }
  774.         else
  775.             rsrc_obfix(tree,index++);
  776.  
  777.         if (obj->ob_x==0 && obj->ob_width>max_w)
  778.             obj->ob_width = max_w;
  779.  
  780.         if (obj->ob_flags & LASTOB)
  781.             break;
  782.  
  783.         obj++;
  784.     }
  785.  
  786.     fix_objects(tree,scaling,orig_cw,orig_ch);
  787. }
  788.  
  789. void rsrc_init(int n_tree,int n_obs,int n_frstr,int n_frimg,int scaling,char **rs_strings,long *rs_frstr,BITBLK *rs_bitblk,
  790.                long *rs_frimg,ICONBLK *rs_iconblk,TEDINFO *rs_tedinfo,OBJECT *rs_object,OBJECT **rs_trindex,RS_IMDOPE *rs_imdope,int orig_cw,int orig_ch)
  791. {
  792.     reg OBJECT  *obj;
  793.     reg int tree,obi,index;
  794.  
  795.     for (obj = rs_object; obj < (rs_object+n_obs); obj++)
  796.     {
  797.         switch((unsigned char) obj->ob_type)
  798.         {
  799.         case G_TEXT:
  800.         case G_BOXTEXT:
  801.         case G_FTEXT:
  802.         case G_FBOXTEXT:
  803.             obj->ob_spec.tedinfo = &rs_tedinfo[obj->ob_spec.index];
  804.             obj->ob_spec.tedinfo->te_ptext = rs_strings[(int) obj->ob_spec.tedinfo->te_ptext];
  805.             obj->ob_spec.tedinfo->te_ptmplt = rs_strings[(int) obj->ob_spec.tedinfo->te_ptmplt];
  806.             obj->ob_spec.tedinfo->te_pvalid = rs_strings[(int) obj->ob_spec.tedinfo->te_pvalid];
  807.             break;
  808.         case G_BUTTON:
  809.         case G_STRING:
  810.         case G_TITLE:
  811.             obj->ob_spec.free_string = rs_strings[(int) obj->ob_spec.index];
  812.             break;
  813.         case G_IMAGE:
  814.             index = (int) obj->ob_spec.index,
  815.             rs_bitblk[index].bi_pdata = (void *) rs_imdope[(int) rs_bitblk[index].bi_pdata].image;
  816.             obj->ob_spec.bitblk = &rs_bitblk[index];
  817.             break;
  818.         case G_ICON:
  819.             index = (int) obj->ob_spec.index,
  820.             rs_iconblk[index].ib_pmask = rs_imdope[(int) rs_iconblk[index].ib_pmask].image;
  821.             rs_iconblk[index].ib_pdata = rs_imdope[(int) rs_iconblk[index].ib_pdata].image;
  822.             rs_iconblk[index].ib_ptext = rs_strings[(int) rs_iconblk[index].ib_ptext];
  823.             obj->ob_spec.iconblk = &rs_iconblk[index];
  824.             break;
  825.         }
  826.     }
  827.  
  828.     for (obi=0;obi<n_frstr;obi++)
  829.         rs_frstr[obi] = (long) rs_strings[(int) rs_frstr[obi]];
  830.  
  831.     for (obi=0;obi<n_frimg;obi++)
  832.     {
  833.         index = (int) rs_frimg[obi];
  834.         rs_bitblk[index].bi_pdata = (void *) rs_imdope[(int) rs_bitblk[index].bi_pdata].image;
  835.         rs_frimg[obi] = (long) &rs_bitblk[index];
  836.     }
  837.  
  838.     for (tree = 0; tree < n_tree; tree++)
  839.     {
  840.         rs_trindex[tree] = &rs_object[(int) rs_trindex[tree]];
  841.         rsrc_calc(rs_trindex[tree],scaling,orig_cw,orig_ch);
  842.     }
  843. }
  844.  
  845. void fix_objects(OBJECT *tree,int scaling,int orig_cw,int orig_ch)
  846. {
  847.     reg OBJECT *org=tree;
  848.     reg int xtype,modal,index=0;
  849.  
  850.     do
  851.     {
  852.         tree++;index++;
  853.  
  854.         switch ((unsigned char) tree->ob_type)
  855.         {
  856.         case G_ICON:
  857.         case G_IMAGE:
  858.             trans_image(tree);
  859.             scale_image(tree,scaling,orig_cw,orig_ch);
  860.             break;
  861.         default:
  862.             {
  863.                 modal = tree->ob_type & (G_MODAL|G_UNMODAL);
  864.                 xtype = (tree->ob_type & G_TYPE)>>8;
  865.  
  866.                 switch(xtype)
  867.                 {
  868.                 case HEADER:
  869.                     {
  870.                         reg OBJECT *par = &org[ob_get_parent(org,index)];
  871.                         reg int frame = par->ob_spec.obspec.framesize;
  872.                         tree->ob_y -= (tree->ob_height>>1) + (1 - frame);
  873.                         if (frame<0)
  874.                             tree->ob_y++;
  875.                         if (par->ob_state & OUTLINED)
  876.                             tree->ob_y--;
  877.                     }
  878.                     break;
  879.                 case CHECKBOX:
  880.                 case CHKHOTKEY:
  881.                     if (xtype==CHKHOTKEY)
  882.                         tree->ob_type = G_CHK;
  883.                     else
  884.                         tree->ob_type = G_USERDEF;
  885.                     tree->ob_spec.userblk=&checkblk;
  886.                     break;
  887.                 case UNDERLINE:
  888.                     tree->ob_type = G_USERDEF;
  889.                     tree->ob_state &= 0x00ff;
  890.                     tree->ob_state |= tree->ob_spec.obspec.framesize<<8;
  891.                     tree->ob_spec.userblk = &unlnblk;
  892.                     tree->ob_height = 1;
  893.                     break;
  894.                 case CYCLE_BUTTON:
  895.                     tree->ob_type = G_USERDEF;
  896.                     tree->ob_spec.userblk = &cycleblk;
  897.                     tree->ob_x--;
  898.                     tree->ob_y--;
  899.                     tree->ob_width = gr_dcw + 4;
  900.                     tree->ob_height = gr_ch + 4;
  901.                     break;
  902.                 case RADIO:
  903.                 case RBHOTKEY:
  904.                     if (xtype == RBHOTKEY)
  905.                         tree->ob_type = G_RB;
  906.                     else
  907.                         tree->ob_type = G_USERDEF;
  908.                     tree->ob_spec.userblk = &rbuttblk;
  909.                     break;
  910.                 case ARROW_LEFT:
  911.                 case ARROW_RIGHT:
  912.                 case ARROW_DOWN:
  913.                 case ARROW_UP:
  914.                     tree->ob_spec.userblk = &arrows;
  915.                     tree->ob_type = (xtype<<8)|G_USERDEF;
  916.                     break;
  917.                 case HOTKEY:
  918.                 case INDHOTKEY:
  919.                     {
  920.                         reg OBJECT *par = &org[ob_get_parent(org,index)];
  921.  
  922.                         if (xtype == INDHOTKEY)
  923.                             tree->ob_type = G_IND;
  924.                         else
  925.                             tree->ob_type = G_HOTKEY;
  926.  
  927.                         tree->ob_state &= 0x00ff;
  928.                         tree->ob_state |= UpperChar(tree->ob_spec.obspec.character)<<8;
  929.                         tree->ob_height = 1;
  930.                         tree->ob_spec.userblk = &hotkeyblk;
  931.  
  932.                         switch((unsigned char) par->ob_type)
  933.                         {
  934.                         case G_TEXT:
  935.                         case G_FTEXT:
  936.                             if (par->ob_spec.tedinfo->te_font==SMALL)
  937.                                 tree->ob_y = ((par->ob_height+gr_sh)>>1)+2;
  938.                             else
  939.                                 tree->ob_y = ((par->ob_height+gr_ch)>>1) - 1;
  940.                             break;
  941.                         case G_BOXTEXT:
  942.                         case G_FBOXTEXT:
  943.                             if (par->ob_spec.tedinfo->te_font==SMALL)
  944.                             {
  945.                                 tree->ob_y = ((par->ob_height+gr_sh)>>1)+2;
  946.                                 break;
  947.                             }
  948.                         case G_BUTTON:
  949.                         case G_BOXCHAR:
  950.                             if (par->ob_height==gr_ch)
  951.                             {
  952.                                 if (big_img==TRUE)
  953.                                 {
  954.                                     par->ob_height += 3;
  955.                                     par->ob_y--;
  956.                                 }
  957.                                 else
  958.                                     par->ob_height++;
  959.                             }
  960.  
  961.                             tree->ob_y = (par->ob_height>>1)+(gr_ch>>1);
  962.                             break;
  963.                         default:
  964.                             tree->ob_y = gr_ch - 1;
  965.                         }
  966.                     }
  967.                     break;
  968.                 case FLYDIAL:
  969.                     tree->ob_spec.userblk = &flyblk;
  970.                     tree->ob_type = G_FLY;
  971.  
  972.                     tree->ob_x = org->ob_width - gr_dcw - 1;
  973.                     tree->ob_y = -3;
  974.                     tree->ob_width = gr_dcw + 4;
  975.                     tree->ob_height = gr_ch + 4;
  976.                     break;
  977.                 case ATTR_TEXT:
  978.                     {
  979.                         reg char *string = NULL;
  980.                         reg int font_id,font_size,color,center,mode;
  981.  
  982.                         switch ((unsigned char) tree->ob_type)
  983.                         {
  984.                         case G_TITLE:
  985.                         case G_BUTTON:
  986.                         case G_STRING:
  987.                             string = tree->ob_spec.free_string;
  988.                             color = BLACK;
  989.                             font_id = ibm_font_id;
  990.                             font_size = ibm_font;
  991.                             center = 0;
  992.                             mode = MD_TRANS;
  993.                             break;
  994.                         case G_FTEXT:
  995.                         case G_FBOXTEXT:
  996.                         case G_TEXT:
  997.                         case G_BOXTEXT:
  998.                             {
  999.                                 TEDINFO *ted = tree->ob_spec.tedinfo;
  1000.  
  1001.                                 string = ted->te_ptext;
  1002.  
  1003.                                 switch (ted->te_font)
  1004.                                 {
  1005.                                 case SMALL:
  1006.                                     font_id = small_font_id;
  1007.                                     font_size = small_font;
  1008.                                     break;
  1009.                                 case IBM:
  1010.                                     font_id = ibm_font_id;
  1011.                                     font_size = ibm_font;
  1012.                                     break;
  1013.                                 default:
  1014.                                     font_id = ted->te_fontid;
  1015.                                     font_size = -ted->te_fontsize;
  1016.                                     if (font_id!=small_font_id && font_id!=ibm_font_id && fonts_loaded<0 && vq_gdos())
  1017.                                         fonts_loaded = vst_load_fonts(x_handle,0);
  1018.                                 }
  1019.  
  1020.                                 color = (ted->te_color>>8) & 15;
  1021.                                 mode = (ted->te_color & 128) ? MD_REPLACE : MD_TRANS;
  1022.                                 center = ted->te_just;
  1023.                             }
  1024.                             break;
  1025.                         }
  1026.  
  1027.                         if (string)
  1028.                         {
  1029.                             reg V_LIST *list = &v_list;
  1030.                             reg X_TEXT *v_text;
  1031.  
  1032.                             for (;;)
  1033.                             {
  1034.                                 if (list->index<128)
  1035.                                 {
  1036.                                     v_text = list->start + list->index;
  1037.                                     list->index++;
  1038.                                     break;
  1039.                                 }
  1040.                                 else if (list->next)
  1041.                                     list = list->next;
  1042.                                 else
  1043.                                 {
  1044.                                     list->next = (V_LIST *) calloc(1,sizeof(V_LIST));
  1045.                                     if ((list = list->next)!=NULL)
  1046.                                     {
  1047.                                         if ((v_text = list->start = (X_TEXT *) calloc(128,sizeof(X_TEXT)))==NULL)
  1048.                                             Mfree(list);
  1049.                                     }
  1050.                                     else
  1051.                                         v_text = NULL;
  1052.                                     break;
  1053.                                 }
  1054.                             }
  1055.  
  1056.                             if (v_text)
  1057.                             {
  1058.                                 v_text->text_blk.ub_code = draw_text;
  1059.                                 v_text->text_blk.ub_parm = (long) v_text;
  1060.  
  1061.                                 v_text->font_id    = font_id;
  1062.                                 v_text->font_size = font_size;
  1063.                                 v_text->color = color;
  1064.                                 v_text->center = center;
  1065.                                 v_text->mode = mode;
  1066.                                 v_text->string = string;
  1067.  
  1068.                                 tree->ob_type = G_XTEXT;
  1069.                                 tree->ob_flags &= ~EDITABLE;
  1070.                                 tree->ob_spec.userblk = &v_text->text_blk;
  1071.                             }
  1072.                         }
  1073.                     }
  1074.                     break;
  1075.                 default:
  1076.                     if (tree->ob_type==G_STRING && (tree->ob_state & DISABLED))
  1077.                         if (tree->ob_spec.free_string[0]=='-')
  1078.                         {
  1079.                             tree->ob_type = G_USERDEF;
  1080.                             tree->ob_spec.userblk = &menublk;
  1081.                         }
  1082.                 }
  1083.                 tree->ob_type |= modal;
  1084.             }
  1085.         }
  1086.     }
  1087.     while(!(tree->ob_flags & LASTOB));
  1088. }
  1089.  
  1090. static void find_fly(DIAINFO *info)
  1091. {
  1092.     reg OBJECT *tree=info->di_tree;
  1093.     reg int type;
  1094.  
  1095.     info->di_fly = FALSE;
  1096.     do
  1097.     {
  1098.         tree++;
  1099.         type = tree->ob_type & G_TYPE;
  1100.         if (type==G_FLY || (type>>8)==USERFLY)
  1101.         {
  1102.             tree->ob_state &= ~DISABLED;
  1103.             tree->ob_flags &= ~HIDETREE;
  1104.  
  1105.             switch (info->di_flag)
  1106.             {
  1107.             case OPENED:
  1108.                 tree->ob_state |= DISABLED;
  1109.                 break;
  1110.             case WINDOW:
  1111.             case WIN_MODAL:
  1112.                 tree->ob_flags |= HIDETREE;
  1113.                 break;
  1114.             case FLYING:
  1115.                 info->di_fly = TRUE;
  1116.                 break;
  1117.             }
  1118.         }
  1119.     }
  1120.     while (!(tree->ob_flags & LASTOB));
  1121. }
  1122.  
  1123. static void dial_center(OBJECT *tree,boolean center,int xy,int wh)
  1124. {
  1125.     int x,y,w,h;
  1126.  
  1127.     switch (center)
  1128.     {
  1129.     case TRUE:
  1130.         {
  1131.             _mouse_pos(&x,&y);
  1132.             tree->ob_x = x - (tree->ob_width>>1);
  1133.             tree->ob_y = y - (tree->ob_height>>1);
  1134.             break;
  1135.         }
  1136.     case FAIL:
  1137.         if (tree->ob_x>=desk.g_x && tree->ob_y>=desk.g_y)
  1138.             break;
  1139.     case FALSE:
  1140.         {
  1141.             INFOVSCR *vscr;
  1142.  
  1143.             form_center(tree,&x,&y,&w,&h);
  1144.             if (get_cookie(COOKIE_VSCR,(long *) &vscr) && (vscr->cookie==COOKIE_XBRA))
  1145.             {
  1146.                 tree->ob_x = vscr->x + ((vscr->w - w)>>1);
  1147.                 tree->ob_y = vscr->y + ((vscr->h - h)>>1);
  1148.             }
  1149.         }
  1150.     }
  1151.     dial_pos(tree,xy,wh);
  1152. }
  1153.  
  1154. static void dial_pos(OBJECT *tree,int xy,int wh)
  1155. {
  1156.     reg int d;
  1157.  
  1158.     if ((d=(tree->ob_x + tree->ob_width + wh)) > clip.v_x2)
  1159.         tree->ob_x -= d - clip.v_x2;
  1160.  
  1161.     if (_dial_round)
  1162.     {
  1163.         tree->ob_x &= 0xFFF8;
  1164.         if (tree->ob_x < (clip.v_x1+xy))
  1165.             tree->ob_x = (clip.v_x1+xy+7) & 0xFFF8;
  1166.     }
  1167.     else
  1168.         Max(&tree->ob_x,clip.v_x1+xy);
  1169.  
  1170.     if ((d=(tree->ob_y + tree->ob_height + wh)) > clip.v_y2)
  1171.         tree->ob_y -= d - clip.v_y2;
  1172.     Max(&tree->ob_y,clip.v_y1+xy);
  1173. }
  1174.  
  1175. static WIN fly={0,0,0,0,0,0,0,0};
  1176.  
  1177. static boolean open_flydialog(OBJECT *tree, DIAINFO *info, boolean center,boolean box)
  1178. {
  1179.     if (_dia_len<MAX_DIALS && (_dia_len==0 || _dia_list[_dia_len-1]->di_flag!=OPENED))
  1180.     {
  1181.         _beg_ctrl();
  1182.         dial_center(tree,center,4,4);
  1183.         _rc_sc_savetree(tree,&info->di_rc);
  1184.  
  1185.         if (info->di_rc.valid)
  1186.             info->di_flag = FLYING;
  1187.         else
  1188.         {
  1189.             info->di_flag = OPENED;
  1190.             form_dial(FMD_START,0,0,0,0,tree->ob_x-3,tree->ob_y-3,tree->ob_width+6,tree->ob_height+6);
  1191.         }
  1192.  
  1193.         info->di_tree = tree;
  1194.         info->di_win = &fly;
  1195.         find_fly(info);
  1196.  
  1197.         if (box)
  1198.             graf_growbox (max_w>>1,max_h>>1,1,1,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height);
  1199.         _dia_list[_dia_len++] = info;
  1200.  
  1201.         return (TRUE);
  1202.     }
  1203.     else
  1204.         return (FALSE);
  1205. }
  1206.  
  1207. void close_dialog(DIAINFO *info,boolean box)
  1208. {
  1209.     reg OBJECT *tree=info->di_tree;
  1210.  
  1211.     switch (info->di_flag)
  1212.     {
  1213.     case WINDOW:
  1214.     case WIN_MODAL:
  1215.         {
  1216.             reg int i;
  1217.  
  1218.             for (i=0;i<win_len;i++)
  1219.                 if (win_list[i]==info)
  1220.                     break;
  1221.  
  1222.             if (i>=win_len)
  1223.                 return;
  1224.  
  1225.             win_len = max(win_len-1,0);
  1226.             for (;i<win_len;i++)
  1227.                 win_list[i] = win_list[i+1];
  1228.  
  1229.         #ifndef SMALL_EGEM
  1230.             _insert_history(info);
  1231.         #endif
  1232.  
  1233.             close_window(info->di_win,box);
  1234.  
  1235.             if (info->di_flag==WIN_MODAL && _menu!=NULL)
  1236.             {
  1237.                 for (i=win_len;--i>=0;)
  1238.                     if (win_list[i]->di_flag==WIN_MODAL)
  1239.                         break;
  1240.                 if (i<0)
  1241.                     menu_enable(TRUE);
  1242.             }
  1243.         }
  1244.         break;
  1245.     case OPENED:
  1246.     case FLYING:
  1247.         {
  1248.             if (_dia_len==0 || info!=_dia_list[_dia_len-1])
  1249.                 return;
  1250.  
  1251.             _dia_len = max(_dia_len-1,0);
  1252.  
  1253.         #ifndef SMALL_EGEM
  1254.             _insert_history(info);
  1255.         #endif
  1256.  
  1257.             if (box)
  1258.                 graf_shrinkbox (max_w>>1,max_h>>1,1,1,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height);
  1259.  
  1260.             if (info->di_flag==OPENED)
  1261.                 form_dial(FMD_FINISH,0,0,0,0,tree->ob_x-3,tree->ob_y-3,tree->ob_width+6,tree->ob_height+6);
  1262.             else
  1263.             {
  1264.                 MouseOff();
  1265.                 rc_sc_restore(info->di_rc.area.g_x,info->di_rc.area.g_y,&info->di_rc,TRUE);
  1266.                 MouseOn();
  1267.             }
  1268.  
  1269.             _end_ctrl();
  1270.             _reset_mouse();
  1271.         }
  1272.     }
  1273.  
  1274.     memset(info,0,sizeof(DIAINFO));
  1275. }
  1276.  
  1277. #ifdef DEBUG
  1278.  
  1279. void _check_hotkeys(OBJECT *tree)
  1280. {
  1281.     reg OBJECT *obj=tree;
  1282.     reg char hotkeys[128],*p=hotkeys,c;
  1283.     reg int index = 0;
  1284.     char msg[128];
  1285.  
  1286.     do
  1287.     {
  1288.         obj++;
  1289.         index++;
  1290.  
  1291.         switch (obj->ob_type & G_TYPE)
  1292.         {
  1293.         case G_IND:
  1294.         case G_HOTKEY:
  1295.             c = obj->ob_state>>8;
  1296.             if (c && !(tree[ob_get_parent(tree,index)].ob_flags & HIDETREE))
  1297.             {
  1298.                 *p = '\0';
  1299.                 if (strchr(hotkeys,c)==NULL)
  1300.                     *p++ = c;
  1301.                 else
  1302.                 {
  1303.                     sprintf(msg,HOTKEY_ERR,c,index);
  1304.                     form_alert(1,msg);
  1305.                 }
  1306.             }
  1307.         }
  1308.     }
  1309.     while (!(obj->ob_flags & LASTOB));
  1310. }
  1311.  
  1312. #endif
  1313.  
  1314. int get_dialog_info(int *fly_dials,int *win_dials,int *wins,DIAINFO **top)
  1315. {
  1316.     if (fly_dials)
  1317.         *fly_dials = _dia_len;
  1318.     if (win_dials)
  1319.         *win_dials = win_len;
  1320.     if (wins)
  1321.         *wins = _opened;
  1322.  
  1323.     if (_popup)
  1324.         return (FAIL);
  1325.     else if (_dia_len>0)
  1326.     {
  1327.         if (top)
  1328.             *top = _dia_list[_dia_len-1];
  1329.         return (FALSE);
  1330.     }
  1331.     else if (menu_dropped())
  1332.         return (FAIL);
  1333.     else
  1334.         return (TRUE);
  1335. }
  1336.  
  1337. boolean open_dialog(OBJECT *tree,DIAINFO *info,char *win_name,char *icon_name,OBJECT *icon,
  1338.                     boolean center,boolean box,int mode,int edit,SLINFO **slider)
  1339. {
  1340.     reg OBJECT *obj = tree;
  1341. #ifdef SMALL_EGEM
  1342.     reg int i,modal,type,flg;
  1343. #else
  1344.     reg int i,eobjc,iobjc,modal,type,flg;
  1345.     int old_ed = info->di_ed_obj,old_index = info->di_ed_index;
  1346.     int edit_rect[4],ob_x,ob_y;
  1347. #endif
  1348.     memset((void *) info,0,sizeof(DIAINFO));
  1349.     for (i=0;i<win_len;i++)
  1350.         if (win_list[i]->di_flag==WIN_MODAL)
  1351.         {
  1352.             mode |= MODAL;
  1353.             break;
  1354.         }
  1355.  
  1356.     do
  1357.     {
  1358.         obj++;
  1359.         modal = obj->ob_type & (G_MODAL|G_UNMODAL);
  1360.         if (((obj->ob_type & G_TYPE)>>8)==HEADER)
  1361.         {
  1362.             switch((unsigned char) obj->ob_type)
  1363.             {
  1364.             case G_TEXT:
  1365.             case G_BOXTEXT:
  1366.                 if (dial_tframe)
  1367.                     obj->ob_type = G_BOXTEXT|modal;
  1368.                 else
  1369.                     obj->ob_type = G_TEXT|modal;
  1370.                 goto _set_title;
  1371.             case G_FTEXT:
  1372.             case G_FBOXTEXT:
  1373.                 if (dial_tframe)
  1374.                     obj->ob_type = G_FBOXTEXT|modal;
  1375.                 else
  1376.                     obj->ob_type = G_FTEXT|modal;
  1377.                 _set_title:
  1378.                 obj->ob_type |= (HEADER<<8);
  1379.                 obj->ob_spec.tedinfo->te_font = (dial_tsmall) ? SMALL : IBM;
  1380.                 obj->ob_spec.tedinfo->te_just = (dial_tframe) ? 2 : 0;
  1381.                 break;
  1382.             }
  1383.         }
  1384.     }
  1385.     while (!(obj->ob_flags & LASTOB));
  1386.  
  1387.     tree->ob_state |= OUTLINED;
  1388.     tree->ob_state &= ~SHADOWED;
  1389.  
  1390.     tree->ob_spec.obspec.interiorcol = dial_color;
  1391.     tree->ob_spec.obspec.fillpattern = dial_pattern;
  1392.     tree->ob_spec.obspec.framecol     = BLACK;
  1393.  
  1394.     if ((mode & WIN_DIAL)==0 || _dia_len>0 || open_windialog(tree,info,win_name,icon_name,icon,mode,center,box)==FALSE)
  1395.         if (mode & FLY_DIAL)
  1396.             open_flydialog(tree,info,center,box);
  1397.  
  1398.     if (info->di_flag>CLOSED)
  1399.     {
  1400.         if (slider!=NULL && *slider!=NULL)
  1401.         {
  1402.             info->di_slider = (void *) slider;
  1403.             while (*slider!=NULL)
  1404.                 (*slider++)->sl_info = info;
  1405.         }
  1406.  
  1407.     #ifndef SMALL_EGEM
  1408.         edit_rect[0] = max_w;
  1409.         edit_rect[1] = max_h;
  1410.         edit_rect[2] = edit_rect[3] = 0;
  1411.  
  1412.         if (edit<=0)
  1413.             edit = old_ed;
  1414.  
  1415.         eobjc = iobjc = FAIL;
  1416.     #endif
  1417.  
  1418.         info->di_insert = TRUE;
  1419.         info->di_inddef = info->di_ed_obj = info->di_ed_index = info->di_default = info->di_help = info->di_undo = FAIL;
  1420.  
  1421.         modal = (info->di_flag!=WINDOW);
  1422.         obj = tree;
  1423.         i = 0;
  1424.  
  1425.         do
  1426.         {
  1427.             obj++;
  1428.             i++;
  1429.  
  1430.             type = obj->ob_type;
  1431.             if (type & G_MODAL)
  1432.             {
  1433.                 if (modal)
  1434.                     obj->ob_flags &= ~HIDETREE;
  1435.                 else
  1436.                     obj->ob_flags |= HIDETREE;
  1437.             }
  1438.             else if (type & G_UNMODAL)
  1439.             {
  1440.                 if (modal)
  1441.                     obj->ob_flags |= HIDETREE;
  1442.                 else
  1443.                     obj->ob_flags &= ~HIDETREE;
  1444.             }
  1445.  
  1446.             type &= G_TYPE;
  1447.             if ((flg = obj->ob_flags) & DEFAULT)
  1448.             {
  1449.                 if (!_is_hidden(tree,i))
  1450.                 {
  1451.                 #ifdef DEBUG
  1452.                     if (info->di_default>0)
  1453.                         form_alert(1,DEFAULT_ERR);
  1454.                     else
  1455.                 #endif
  1456.                         info->di_default = i;
  1457.                 }
  1458.             }
  1459.  
  1460.         #ifndef SMALL_EGEM
  1461.             if (flg & EDITABLE)
  1462.             {
  1463.                 if ((unsigned char) type!=G_FTEXT && (unsigned char) type!=G_FBOXTEXT)
  1464.                     obj->ob_flags &= ~EDITABLE;
  1465.                 else if (!_is_hidden(tree,i))
  1466.                 {
  1467.                     objc_offset(tree,i,&ob_x,&ob_y);
  1468.  
  1469.                     Min(&edit_rect[0],ob_x);
  1470.                     Min(&edit_rect[1],ob_y);
  1471.                     Max(&edit_rect[2],ob_x+obj->ob_width-1);
  1472.                     Max(&edit_rect[3],ob_y+obj->ob_height-1);
  1473.  
  1474.                     info->di_ed_cnt++;
  1475.  
  1476.                     if ((type>>8)==TXTDEFAULT)
  1477.                     {
  1478.                     #ifdef DEBUG
  1479.                         if (iobjc>0)
  1480.                             form_alert(1,INDDEFAULT_ERR);
  1481.                         else
  1482.                     #endif
  1483.                             iobjc = i;
  1484.                     }
  1485.  
  1486.                     if (eobjc<0 || i==edit)
  1487.                         eobjc = i;
  1488.                 }
  1489.             }
  1490.         #endif
  1491.  
  1492.         #ifdef DEBUG
  1493.             if (type==G_CHK || type==G_RB)
  1494.             {
  1495.                 if (!_is_hidden(tree,i))
  1496.                 {
  1497.                     reg char *err=NULL,msg[40];
  1498.  
  1499.                     switch (_get_hotkey(tree,i))
  1500.                     {
  1501.                     case FAIL:
  1502.                         err = (type==G_RB) ? RBHOTKEY_ERR_A : CHKHOTKEY_ERR_A;
  1503.                         break;
  1504.                     case FALSE:
  1505.                         err = (type==G_RB) ? RBHOTKEY_ERR_B : CHKHOTKEY_ERR_B;
  1506.                     }
  1507.  
  1508.                     if (err)
  1509.                     {
  1510.                         sprintf(msg,err,i);
  1511.                         form_alert(1,msg);
  1512.                     }
  1513.                 }
  1514.             }
  1515.             else
  1516.             {
  1517.                 type >>= 8;
  1518.                 if (type==HELP_BTN && !_is_hidden(tree,i))
  1519.                 {
  1520.                     if (info->di_help>0)
  1521.                         form_alert(1,HELP_ERR);
  1522.                     else
  1523.                         info->di_help = i;
  1524.                 }
  1525.                 else if (type==UNDO_BTN && !_is_hidden(tree,i))
  1526.                 {
  1527.                     if (info->di_undo>0)
  1528.                         form_alert(1,UNDO_ERR);
  1529.                     else
  1530.                         info->di_undo = i;
  1531.                 }
  1532.             }
  1533.         #else
  1534.             type >>= 8;
  1535.             if (type==HELP_BTN && !_is_hidden(tree,i))
  1536.                 info->di_help = i;
  1537.             else if (type==UNDO_BTN && !_is_hidden(tree,i))
  1538.                 info->di_undo = i;
  1539.         #endif
  1540.         }
  1541.         while (!(flg & LASTOB));
  1542.  
  1543.     #ifndef SMALL_EGEM
  1544.         rc_array_to_grect(edit_rect,&info->di_edit);
  1545.         info->di_edit.g_x -= tree->ob_x;
  1546.         info->di_edit.g_y -= tree->ob_y;
  1547.     #endif
  1548.  
  1549.         if (info->di_flag<WINDOW)
  1550.         {
  1551.             objc_draw(tree,ROOT,MAX_DEPTH,desk.g_x,desk.g_y,desk.g_w,desk.g_h);
  1552.             info->di_drawn = TRUE;
  1553.         }
  1554.  
  1555.     #ifdef DEBUG
  1556.         _check_hotkeys(tree);
  1557.     #endif
  1558.  
  1559.     #ifndef SMALL_EGEM
  1560.         if (eobjc>0)
  1561.             _set_cursor(info,eobjc,(eobjc==old_ed && old_index>=0) ? old_index : 0x1000);
  1562.  
  1563.         if (iobjc>0 && info->di_default>0 && iobjc!=info->di_default)
  1564.         {
  1565.             info->di_inddef = iobjc;
  1566.             test_inddefault(info);
  1567.         }
  1568.     #endif
  1569.  
  1570.         return(TRUE);
  1571.     }
  1572.     else
  1573.         return(FALSE);
  1574. }
  1575.  
  1576. void _set_menu(void)
  1577. {
  1578.     if (_cycle>0)
  1579.         menu_item_enable(_cycle,(_opened>1) ? 1 : 0);
  1580.     if (_close>0)
  1581.         menu_item_enable(_close,(_opened>0) ? 1 : 0);
  1582. }
  1583.  
  1584. static void dial_calc(DIAINFO *info,OBJECT *tree,GRECT *out)
  1585. {
  1586.     *out = *(GRECT *) &tree->ob_x;
  1587.     out->g_x -= info->di_xy_off;
  1588.     out->g_y -= info->di_xy_off;
  1589.     out->g_w += info->di_wh_off;
  1590.     out->g_h += info->di_wh_off;
  1591. }
  1592.  
  1593. static boolean open_windialog(OBJECT *tree,DIAINFO *info,char *win_name,char *icon_name,OBJECT *icon,int mode,boolean center,boolean box)
  1594. {
  1595.     if (win_len<MAX_DIALS)
  1596.     {
  1597.         GRECT in,area;
  1598.         int typ = NAME|MOVER;
  1599.  
  1600.         info->di_mode = mode;
  1601.  
  1602.         if (!(mode & MODAL))
  1603.             typ |= CLOSER;
  1604.  
  1605.         if (!(mode & NO_ICONIFY))
  1606.             typ |= SMALLER;
  1607.  
  1608.         if (mode & WD_HSLIDER)
  1609.             typ |= HSLIDE|LFARROW|RTARROW;
  1610.  
  1611.         if (mode & WD_VSLIDER)
  1612.             typ |= VSLIDE|UPARROW|DNARROW;
  1613.  
  1614.         if (mode & WD_SIZER)
  1615.             typ |= SIZER;
  1616.  
  1617.         if (mode & WD_FULLER)
  1618.             typ |= FULLER;
  1619.  
  1620.         if (mode & WD_INFO)
  1621.             typ |= INFO;
  1622.  
  1623.         if (mode & FRAME)
  1624.         {
  1625.             info->di_xy_off = 3;
  1626.             info->di_wh_off = 5;
  1627.         }
  1628.         else
  1629.         {
  1630.             info->di_xy_off = -2;
  1631.             info->di_wh_off = -4;
  1632.             tree->ob_state &= ~OUTLINED;
  1633.         }
  1634.  
  1635.         dial_center(tree,center,0,info->di_wh_off-info->di_xy_off+3);
  1636.         dial_calc(info,tree,&in);
  1637.         window_calc(WC_BORDER,typ,&in,&area);
  1638.  
  1639.         if (_dial_round)
  1640.             while (area.g_x<clip.v_x1)
  1641.             {
  1642.                 tree->ob_x += 8;
  1643.                 area.g_x += 8;
  1644.             }
  1645.         else if (area.g_x<clip.v_x1)
  1646.         {
  1647.             tree->ob_x = clip.v_x1 - area.g_x;
  1648.             area.g_x = clip.v_x1;
  1649.         }
  1650.  
  1651.         if (area.g_y<clip.v_y1)
  1652.         {
  1653.             tree->ob_y += clip.v_y1 - area.g_y;
  1654.             area.g_y = clip.v_y1;
  1655.         }
  1656.  
  1657.         _no_av_win = (tree==_alert_tree);
  1658.         if ((info->di_win=open_window(win_name,icon_name,NULL,icon,typ,box,0,0,NULL,&area,NULL,(R_PROC) redraw_dialog))!=NULL)
  1659.         {
  1660.             info->di_win->dialog = (void *) info;
  1661.  
  1662.             if (mode & MODAL)
  1663.             {
  1664.                 menu_enable(FALSE);
  1665.                 info->di_flag = WIN_MODAL;
  1666.             }
  1667.             else
  1668.                 info->di_flag = WINDOW;
  1669.  
  1670.             info->di_title = win_name;
  1671.             info->di_tree = tree;
  1672.  
  1673.             find_fly(info);
  1674.             win_list[win_len++]=info;
  1675.             return(TRUE);
  1676.         }
  1677.     }
  1678.     return(FALSE);
  1679. }
  1680.  
  1681. static void move_dialog(DIAINFO *info,GRECT *area)
  1682. {
  1683.     reg WIN *win = info->di_win;
  1684.     reg int fulled = rc_equal(area,&win->max);
  1685.  
  1686.     if (_dial_round)
  1687.     {
  1688.         GRECT work;
  1689.         reg int x;
  1690.  
  1691.         window_calc(WC_WORK,win->gadgets,area,&work);
  1692.         x = work.g_x + info->di_xy_off;
  1693.         area->g_x -= x - (x & ~7);
  1694.  
  1695.         while (area->g_x<desk.g_x)
  1696.             area->g_x += 8;
  1697.     }
  1698.  
  1699.     window_size(win,area);
  1700.     win->fulled = fulled;
  1701. }
  1702.  
  1703. static void redraw_dialog(DIAINFO *info,GRECT *area,GRECT *cursor)
  1704. {
  1705.     objc_draw(info->di_tree,ROOT,MAX_DEPTH,area->g_x,area->g_y,area->g_w,area->g_h);
  1706.     if (info->di_cursor && rc_intersect(cursor,area))
  1707.         rc_sc_invert(area);
  1708. }
  1709.  
  1710. static int cdecl draw_underline(PARMBLK *pb)
  1711. {
  1712.     reg OBJECT *tree = pb->pb_tree,*obj = tree + pb->pb_obj;
  1713.     reg int d,x1,x2,disabled,type = ((obj->ob_type & G_TYPE)==G_USERDEF);
  1714.  
  1715.     if (type)
  1716.     {
  1717.         if ((d=(int) (pb->pb_parm>>8))==0)
  1718.             d = obj->ob_state>>8;
  1719.         _vdi_attr(MD_REPLACE,d,(char) pb->pb_parm);
  1720.         disabled = 0;
  1721.     }
  1722.     else
  1723.     {
  1724.         disabled = tree[ob_get_parent(tree,pb->pb_obj)].ob_state;
  1725.         _vdi_attr((disabled & SELECTED) ? MD_XOR : MD_REPLACE,d=1,(char) (pb->pb_parm));
  1726.  
  1727.         if ((disabled &= DISABLED)!=0)
  1728.             vsl_type(x_handle,7);
  1729.     }
  1730.  
  1731.     if (type && dial_title)
  1732.     {
  1733.         x1 = tree->ob_x + gr_cw;
  1734.         x2 = tree->ob_x + tree->ob_width - gr_cw - 1;
  1735.     }
  1736.     else
  1737.     {
  1738.         x1 = pb->pb_x;
  1739.         x2 = pb->pb_x + pb->pb_w - 1;
  1740.     }
  1741.     _line(x1,pb->pb_y,x2,pb->pb_y);
  1742.  
  1743.     if (type && (obj->ob_state & OUTLINED))
  1744.     {
  1745.         d += d;
  1746.         _line(x1,pb->pb_y+d,x2,pb->pb_y+d);
  1747.     }
  1748.  
  1749.     if (disabled)
  1750.         vsl_type(x_handle,1);
  1751.     return (0);
  1752. }
  1753.  
  1754. static int cdecl draw_box(PARMBLK *pb)
  1755. {
  1756.     reg OBJECT *obj = &pb->pb_tree[pb->pb_obj];
  1757.     reg int disabled = ((pb->pb_tree[obj->ob_next].ob_state)|obj->ob_state) & DISABLED;
  1758.     reg int color = (int) pb->pb_parm;
  1759.  
  1760.     if (obj->ob_state & CHECKED)
  1761.     {
  1762.         _vdi_attr(MD_REPLACE,1,color);
  1763.         _bar(pb->pb_x+1,pb->pb_y+1,pb->pb_w-3,pb->pb_h-3,2,4,color);
  1764.     }
  1765.     else if (big_img==FAIL)
  1766.     {
  1767.         reg int x = pb->pb_x+1,y = pb->pb_y+1,w = pb->pb_w-3,h=pb->pb_w-3;
  1768.  
  1769.         _vdi_attr(MD_REPLACE,1,color);
  1770.         _bar(x,y,w,h,0,FAIL,color);
  1771.  
  1772.         if (pb->pb_currstate & SELECTED)
  1773.         {
  1774.             _line(x,y,x+w,y+h);
  1775.             _line(x+w,y,x,y+h);
  1776.         }
  1777.     }
  1778.     else if (pb->pb_currstate & SELECTED)
  1779.         vrt_copy(box_on,pb,color,0);
  1780.     else
  1781.         vrt_copy(box_off,pb,color,0);
  1782.     return (disabled);
  1783. }
  1784.  
  1785. static int cdecl draw_cyclebutton(PARMBLK *pb)
  1786. {
  1787.     reg int color = (int) pb->pb_parm,w,h;
  1788.  
  1789.     w = gr_dcw;
  1790.     h = gr_ch;
  1791.     if (big_img==FAIL)
  1792.         w--;
  1793.  
  1794.     pb->pb_x++;
  1795.     pb->pb_y++;
  1796.     pb->pb_w = w;
  1797.     pb->pb_h = h;
  1798.  
  1799.     _vdi_attr(MD_REPLACE,1,color);
  1800.     _bar(pb->pb_x+2,pb->pb_y+2,w,h,1,FAIL,color);
  1801.  
  1802.     if (big_img==FAIL)
  1803.     {
  1804.         _bar(pb->pb_x-1,pb->pb_y-1,w+1,h+1,0,FAIL,color);
  1805.         v_set_text(ibm_font_id,ibm_font,color,NULL);
  1806.         v_gtext(x_handle,pb->pb_x+(gr_cw>>1),pb->pb_y,"\x02");
  1807.         if (pb->pb_currstate & SELECTED)
  1808.             rc_sc_invert((GRECT *) &pb->pb_x);
  1809.     }
  1810.     else
  1811.     {
  1812.         _rectangle(pb->pb_x-1,pb->pb_y-1,pb->pb_x+w,pb->pb_y+h);
  1813.         vrt_copy(cycle_but,pb,color,pb->pb_currstate & SELECTED);
  1814.     }
  1815.  
  1816.     return(pb->pb_currstate & DISABLED);
  1817. }
  1818.  
  1819. static int cdecl draw_radiobutton(PARMBLK *pb)
  1820. {
  1821.     reg OBJECT *obj = &pb->pb_tree[pb->pb_obj];
  1822.     reg int disabled = ((pb->pb_tree[obj->ob_next].ob_state)|obj->ob_state) & DISABLED;
  1823.  
  1824.     if (big_img==FAIL)
  1825.     {
  1826.         reg int color = (int) pb->pb_parm;
  1827.  
  1828.         _vdi_attr(MD_REPLACE,1,color);
  1829.         _bar(pb->pb_x+1,pb->pb_y+1,pb->pb_w-3,pb->pb_h-3,0,FAIL,color);
  1830.         if ((pb->pb_currstate & SELECTED) && !disabled)
  1831.             _bar(pb->pb_x+4,pb->pb_y+4,pb->pb_w-9,pb->pb_h-9,1,FAIL,color);
  1832.     }
  1833.     else if (pb->pb_currstate & SELECTED)
  1834.         vrt_copy(radio_on,pb,(int) pb->pb_parm,0);
  1835.     else
  1836.         vrt_copy(radio_off,pb,(int) pb->pb_parm,0);
  1837.     return(disabled);
  1838. }
  1839.  
  1840. static int cdecl draw_arrows(PARMBLK *pb)
  1841. {
  1842.     reg int type = (pb->pb_tree[pb->pb_obj].ob_type & G_TYPE)>>8,color = (int) pb->pb_parm;
  1843.  
  1844.     _vdi_attr(MD_REPLACE,1,color);
  1845.     if (big_img==FAIL)
  1846.     {
  1847.         _bar(pb->pb_x-1,pb->pb_y-1,gr_dcw+1,gr_ch+1,0,FAIL,(pb->pb_currstate & OUTLINED) ? color : 0);
  1848.         v_set_text(ibm_font_id,ibm_font,color,NULL);
  1849.         v_gtext(x_handle,pb->pb_x+(gr_cw>>1),pb->pb_y,c_arrow[type-ARROW_LEFT]);
  1850.         if (pb->pb_currstate & SELECTED)
  1851.             rc_sc_invert((GRECT *) &pb->pb_x);
  1852.     }
  1853.     else
  1854.     {
  1855.         reg int *but,*sel;
  1856.  
  1857.         if (pb->pb_currstate & OUTLINED)
  1858.             _rectangle(pb->pb_x-1,pb->pb_y-1,pb->pb_x+gr_dcw,pb->pb_y+gr_ch);
  1859.  
  1860.         switch (type)
  1861.         {
  1862.         case ARROW_UP:
  1863.             but = arrow_up;
  1864.             sel = arrow_up_sel;
  1865.             break;
  1866.         case ARROW_DOWN:
  1867.             but = arrow_down;
  1868.             sel = arrow_down_sel;
  1869.             break;
  1870.         case ARROW_LEFT:
  1871.             but = arrow_left;
  1872.             sel = arrow_left_sel;
  1873.             break;
  1874.         default:
  1875.             but = arrow_right;
  1876.             sel = arrow_right_sel;
  1877.             break;
  1878.         }
  1879.  
  1880.         if (pb->pb_currstate & SELECTED)
  1881.         {
  1882.             if (sel)
  1883.                 vrt_copy(sel,pb,color,0);
  1884.             else
  1885.                 vrt_copy(but,pb,color,1);
  1886.         }
  1887.         else
  1888.             vrt_copy(but,pb,color,0);
  1889.     }
  1890.     return(pb->pb_currstate & DISABLED);
  1891. }
  1892.  
  1893. static int cdecl draw_fly(PARMBLK *pb)
  1894. {
  1895.     reg int pxy[6],w=pb->pb_w-1,h=pb->pb_h-1;
  1896.  
  1897.     _vdi_attr(MD_REPLACE,1,BLACK);
  1898.     _bar(pb->pb_x,pb->pb_y,w,h,0,FAIL,BLACK);
  1899.  
  1900.     if (pb->pb_tree->ob_state & OUTLINED)
  1901.     {
  1902.         pxy[0] = pb->pb_x + 3;
  1903.         pxy[3] = pxy[1] = pb->pb_y + 3;
  1904.         pxy[4] = pxy[2] = pb->pb_x + pb->pb_w - 4;
  1905.         pxy[5] = pb->pb_y + pb->pb_h - 4;
  1906.         v_pline(x_handle,3,pxy);
  1907.  
  1908.         if (pb->pb_tree->ob_spec.obspec.framesize!=1)
  1909.         {
  1910.             if (big_img==TRUE)
  1911.                 pxy[0]++;
  1912.             else
  1913.                 pxy[0] += 2;
  1914.             pxy[1]++;
  1915.             pxy[2]--;
  1916.             pxy[3]++;
  1917.             pxy[4]--;
  1918.             if (big_img==TRUE)
  1919.                 pxy[5]--;
  1920.             v_pline(x_handle,3,pxy);
  1921.         }
  1922.     }
  1923.  
  1924.     _line(pb->pb_x,pb->pb_y,pb->pb_x + w,pb->pb_y + h);
  1925.     return(pb->pb_currstate & ~SELECTED);
  1926. }
  1927.  
  1928. static int cdecl draw_text(PARMBLK *pb)
  1929. {
  1930.     reg X_TEXT *text = (X_TEXT *) pb->pb_parm;
  1931.     reg int state = pb->pb_tree[pb->pb_obj].ob_state,effect = 0,color = text->color,x=pb->pb_x,y=pb->pb_y;
  1932.     reg int pxy[8];
  1933.  
  1934.     v_set_mode(text->mode);
  1935.     v_set_text(text->font_id,text->font_size,color,NULL);
  1936.  
  1937.     if (state & SELECTED)
  1938.         effect |= 1;
  1939.     if (state & CHECKED)
  1940.         effect |= 8;
  1941.     if (state & CROSSED)
  1942.         effect |= 4;
  1943.     if (state & DISABLED)
  1944.         effect |= 2;
  1945.     if (state & OUTLINED)
  1946.         effect |= 16;
  1947.  
  1948.     if (state & SHADOWED)
  1949.     {
  1950.         vst_effects(x_handle,effect|2);
  1951.  
  1952.         vqt_extent(x_handle,(char *) text->string,&pxy[0]);
  1953.         switch (text->center)
  1954.         {
  1955.         case TE_RIGHT:
  1956.             x += pb->pb_w - pxy[4];
  1957.             break;
  1958.         case TE_CNTR:
  1959.             x += (pb->pb_w - pxy[4])>>1;
  1960.         }
  1961.         y += (pb->pb_h - pxy[5])>>1;
  1962.  
  1963.         v_gtext(x_handle,x+2,y+2,(char *) text->string);
  1964.         vst_effects(x_handle,effect);
  1965.     }
  1966.     else
  1967.     {
  1968.         vst_effects(x_handle,effect);
  1969.  
  1970.         vqt_extent(x_handle,(char *) text->string,&pxy[0]);
  1971.         switch (text->center)
  1972.         {
  1973.         case TE_RIGHT:
  1974.             x += pb->pb_w - pxy[4];
  1975.             break;
  1976.         case TE_CNTR:
  1977.             x += (pb->pb_w - pxy[4])>>1;
  1978.         }
  1979.         y += (pb->pb_h - pxy[5])>>1;
  1980.     }
  1981.  
  1982.     v_gtext(x_handle,x,y,(char *) text->string);
  1983.  
  1984.     if (effect)
  1985.         vst_effects(x_handle,0);
  1986.  
  1987.     return(FALSE);
  1988. }
  1989.  
  1990. static int cdecl draw_menu(PARMBLK *pb)
  1991. {
  1992.     reg int pxy[4];
  1993.  
  1994.     v_set_mode(MD_REPLACE);
  1995.     v_set_fill(BLACK,2,4);
  1996.  
  1997.     pxy[0] = pb->pb_x;
  1998.     pxy[1] = pb->pb_y + (pb->pb_h>>1) - 1;
  1999.     pxy[2] = pxy[0] + pb->pb_w - 1;
  2000.     pxy[3] = pxy[1] + 1;
  2001.     vr_recfl(x_handle,pxy);
  2002.  
  2003.     return(FALSE);
  2004. }
  2005.  
  2006. #ifndef SMALL_EGEM
  2007. static void test_inddefault(DIAINFO *info)
  2008. {
  2009.     reg char *text = ob_get_text(info->di_tree,info->di_inddef,0);
  2010.     if (text!=NULL)
  2011.         ob_disable(info,info->di_tree,info->di_default,(*text!='\0') ? CLEAR_STATE : SET_STATE,info->di_drawn);
  2012. }
  2013. #endif
  2014.  
  2015. void _init_xformdo(XEVENT *event,DIAINFO *info,int top)
  2016. {
  2017.     if (_dia_len>0)
  2018.         event->ev_mflags = MU_KEYBD|MU_BUTTON|MU_NO_HANDLER;
  2019.     else
  2020.         event->ev_mflags = MU_KEYBD|MU_BUTTON|MU_MESAG|MU_NO_HANDLER;
  2021.  
  2022. #ifndef SMALL_EGEM
  2023.     if (info==NULL)
  2024.     {
  2025.         int dummy;
  2026.  
  2027.         info = get_info(&dummy);
  2028.         top = dummy;
  2029.     }
  2030.  
  2031.     _ascii = _ascii_digit = 0;
  2032.  
  2033.     if (!info->di_win->iconified && info->di_ed_obj>0)
  2034.     {
  2035.         _set_cursor(info,FAIL,FAIL);
  2036.  
  2037.         if (info->di_inddef>0)
  2038.             test_inddefault(info);
  2039.  
  2040.         if (top)
  2041.         {
  2042.             mouse_flag = FAIL;
  2043.             _mouse_pos(&event->ev_mmox,&event->ev_mmoy);
  2044.             mouse_cursor(info,event);
  2045.             event->ev_mflags |= MU_M1;
  2046.             return;
  2047.         }
  2048.     }
  2049. #endif
  2050.  
  2051.     if (top)
  2052.     {
  2053.         MouseArrow();
  2054.         mouse_flag = FALSE;
  2055.     }
  2056. }
  2057.  
  2058. void close_all_dialogs(void)
  2059. {
  2060.     while (_dia_len>0)
  2061.         close_dialog(_dia_list[_dia_len-1],FALSE);
  2062.  
  2063.     while (win_len>0)
  2064.         close_dialog(win_list[win_len-1],FALSE);
  2065. }
  2066.  
  2067. void close_all_windows(void)
  2068. {
  2069.     reg WIN *window = _windows;
  2070.     reg int i;
  2071.  
  2072.     close_all_dialogs();
  2073.     if (_opened>0)
  2074.         for (i=MAX_WINDOWS;--i>=0;window++)
  2075.             if (window->handle>0)
  2076.                 close_window(window,FALSE);
  2077. }
  2078.  
  2079. static boolean find_windial(reg int hdl,DIAINFO **info)
  2080. {
  2081.     reg DIAINFO **list=win_list;
  2082.     reg int index;
  2083.  
  2084.     if (hdl>0)
  2085.         for (index=win_len;--index>=0;)
  2086.         {
  2087.             if ((*list++)->di_win->handle==hdl)
  2088.             {
  2089.                 *info = *--list;
  2090.                 return(TRUE);
  2091.             }
  2092.         }
  2093.  
  2094.     return(FALSE);
  2095. }
  2096.  
  2097. static int do_func(DIAINFO *info,int top,int msg,XEVENT *event)
  2098. {
  2099.     reg DIAINFO *new_info;
  2100.     reg int used;
  2101.     int new_top;
  2102.  
  2103.     used = _call_event_handler(msg,event,TRUE);
  2104.     if ((_dia_len+win_len)==0)
  2105.         return (TRUE);
  2106.     else if (used && info && (info!=(new_info=get_info(&new_top)) || new_top!=top))
  2107.         _init_xformdo(event,new_info,new_top);
  2108.  
  2109.     return (FALSE);
  2110. }
  2111.  
  2112. int _messag_handler(int form_do,XEVENT *event,int *obj,DIAINFO **back)
  2113. {
  2114.     int top;
  2115.     DIAINFO *info,*act_info = get_info(&top);
  2116.     WIN *window;
  2117.     reg int *mbuf = event->ev_mmgpbuf,msg = mbuf[0];
  2118.     reg boolean found = FALSE,win = FALSE, modal = FALSE;
  2119.  
  2120.     if (act_info)
  2121.     {
  2122.         switch (msg)
  2123.         {
  2124.         case WIN_CHANGED:
  2125.             win = TRUE;
  2126.             window = *(WIN **) &mbuf[4];
  2127.             if (window!=NULL)
  2128.                 found = find_windial(window->handle,&info);
  2129.             break;
  2130.         case WM_BOTTOMED:
  2131.         case WM_CLOSED:
  2132.         case WM_TOPPED:
  2133.             if (act_info->di_flag==WIN_MODAL)
  2134.                 modal = win = TRUE;
  2135.         case WM_UNTOPPED:
  2136.         case WM_ONTOP:
  2137.         case WM_NEWTOP:
  2138.         case WM_MOVED:
  2139.             found = find_windial(mbuf[3],&info);
  2140.             break;
  2141.         default:
  2142.             if ((act_info->di_mode & WD_SET_SIZE) && (msg==WM_FULLED || msg==WM_SIZED))
  2143.                 found = find_windial(mbuf[3],&info);
  2144.             break;
  2145.         }
  2146.  
  2147.         if (found || win)
  2148.         {
  2149.             event->ev_mwich &= ~MU_MESAG;
  2150.  
  2151.             switch (msg)
  2152.             {
  2153.             case WIN_CHANGED:
  2154.                 if (form_do)
  2155.                 {
  2156.                     _init_xformdo(event,act_info,top);
  2157.                     if (!found)
  2158.                         do_func(act_info,top,MU_MESAG,event);
  2159.                 }
  2160.                 else if (!found)
  2161.                     event->ev_mwich |= MU_MESAG;
  2162.                 break;
  2163.             case WM_BOTTOMED:
  2164.                 if (!modal)
  2165.                 {
  2166.                     window_bottom(info->di_win);
  2167.                     if (info==act_info)
  2168.                         _init_xformdo(event,NULL,FAIL);
  2169.                 }
  2170.                 break;
  2171.             case WM_ONTOP:
  2172.             case WM_NEWTOP:
  2173.             case WM_UNTOPPED:
  2174.                 if (form_do)
  2175.                     _init_xformdo(event,act_info,top);
  2176.                 break;
  2177.             case WM_TOPPED:
  2178.                 if (modal)
  2179.                     info = act_info;
  2180.                 window_top(info->di_win);
  2181.                 if (form_do)
  2182.                     _init_xformdo(event,info,TRUE);
  2183.                 break;
  2184.             case WM_CLOSED:
  2185.                 if (!modal && found)
  2186.                 {
  2187.                     if (back)
  2188.                         *back = info;
  2189.                     if (obj)
  2190.                         *obj = W_CLOSED;
  2191.                     return (TRUE);
  2192.                 }
  2193.                 break;
  2194.             case WM_FULLED:
  2195.                 *(GRECT *) &mbuf[4] = (info->di_win->fulled) ? info->di_win->prev : info->di_win->max;
  2196.             case WM_SIZED:
  2197.             case WM_MOVED:
  2198.                 move_dialog(info,(GRECT *) &mbuf[4]);
  2199.                 _send_msg(info,0,OBJC_SIZED,0,0);
  2200.             #ifndef SMALL_EGEM
  2201.                 if (form_do && info==act_info && top)
  2202.                     mouse_cursor(info,event);
  2203.             #endif
  2204.                 break;
  2205.             }
  2206.         }
  2207.     }
  2208.  
  2209.     switch (msg)
  2210.     {
  2211.     case ACC_TEXT:
  2212.     #ifndef SMALL_EGEM
  2213.         if (act_info!=NULL && act_info->di_ed_obj>0 && (top || _opened==1 || act_info->di_win->handle==_last_top))
  2214.         {
  2215.             reg char *text = *(char **) &mbuf[4];
  2216.             reg int cat = (strpbrk(text,"\r\n")==NULL);
  2217.             reg int ob = act_info->di_ed_obj;
  2218.  
  2219.             do
  2220.             {
  2221.                 text += _insert_buf(act_info,text,cat);
  2222.             } while (*text!='\0' && _next_edit(act_info,FALSE));
  2223.  
  2224.             if (act_info->di_inddef>0 && act_info->di_default>0)
  2225.                 test_inddefault(act_info);
  2226.  
  2227.             if (!cat)
  2228.                 _set_cursor(act_info,ob,FAIL);
  2229.  
  2230.             XAccSendAck(mbuf[1],1);
  2231.             _send_msg(act_info,FAIL,OBJC_EDITED,0,0);
  2232.             event->ev_mwich &= ~MU_MESAG;
  2233.         }
  2234.         else
  2235.     #endif
  2236.         if (!(_xacc_msgs & X_MSG_TEXT))
  2237.         {
  2238.             XAccSendAck(mbuf[1],0);
  2239.             event->ev_mwich &= ~MU_MESAG;
  2240.         }
  2241.         break;
  2242.     case AC_CLOSE:
  2243.         _ac_close = TRUE;
  2244.     case AP_TERM:
  2245.         close_all_windows();
  2246.         if (form_do)
  2247.             do_func(act_info,top,MU_MESAG,event);
  2248.         else
  2249.             event->ev_mwich |= MU_MESAG;
  2250.         _ac_close = FALSE;
  2251.     }
  2252.  
  2253.     if ((win_len+_dia_len)<=0)
  2254.     {
  2255.         if (obj)
  2256.             *obj = W_ABANDON;
  2257.         return (TRUE);
  2258.     }
  2259.     else
  2260.         return (FALSE);
  2261. }
  2262.  
  2263. int X_Form_Do(DIAINFO **back)
  2264. {
  2265.     XEVENT event;
  2266.     DIAINFO *act_info,*winfo;
  2267.     reg int events,do_event,handle;
  2268.     int top,obj;
  2269.  
  2270.     if (back)
  2271.         *back = NULL;
  2272.  
  2273.     if (_dia_len==0 && win_len==0)
  2274.         return (W_ABANDON);
  2275.  
  2276.     memset(&event,0,sizeof(XEVENT));
  2277.  
  2278.     event.ev_mbclicks = 258;
  2279.     event.ev_mbmask = 3;
  2280.  
  2281.     _init_xformdo(&event,NULL,FAIL);
  2282.  
  2283.     for(;;)
  2284.     {
  2285.         events = Event_Multi(&event);
  2286.         if (events & MU_MESAG)
  2287.         {
  2288.             if (_messag_handler(TRUE,&event,&obj,back))
  2289.                 return (obj);
  2290.             else
  2291.                 events = event.ev_mwich;
  2292.         }
  2293.  
  2294.         if (events & MU_BUTTON)
  2295.         {
  2296.             do_event = FAIL;
  2297.             act_info = get_info(&top);
  2298.  
  2299.             if (act_info->di_flag<WINDOW || act_info->di_win->handle==(handle=wind_find(event.ev_mmox,event.ev_mmoy)))
  2300.             {
  2301.                 winfo = act_info;
  2302.                 do_event = top;
  2303.             }
  2304.             else if ((_back_win || (event.ev_mmobutton & 3)==3) && act_info->di_flag!=WIN_MODAL && find_windial(handle,&winfo))
  2305.                 do_event = FALSE;
  2306.  
  2307.             if (do_event>=FALSE && !winfo->di_win->iconified && klickobj(winfo,&event,&obj,do_event)==FALSE)
  2308.             {
  2309.                 if (back)
  2310.                     *back = winfo;
  2311.                 return (obj);
  2312.             }
  2313.  
  2314.             events &= ~MU_BUTTON;
  2315.         }
  2316.  
  2317.         if (events & MU_KEYBD)
  2318.         {
  2319.             act_info = get_info(&top);
  2320.             do_event = (top || act_info->di_win->handle==_last_top);
  2321.  
  2322.             if (toMouse && act_info->di_flag==WINDOW && find_windial(wind_find(event.ev_mmox,event.ev_mmoy),&winfo) && !winfo->di_win->iconified)
  2323.             {
  2324.                 if (winfo!=act_info)
  2325.                     top = FALSE;
  2326.                 act_info = winfo;
  2327.                 do_event = TRUE;
  2328.             }
  2329.  
  2330.             act_info->di_taken = FALSE;
  2331.             if (do_event && !act_info->di_win->iconified)
  2332.             {
  2333.                 obj = key_handler(act_info,event.ev_mmokstate,event.ev_mkreturn,&event);
  2334.                 if (obj!=FAIL && obj)
  2335.                 {
  2336.                     if (back)
  2337.                         *back = act_info;
  2338.                     return (obj);
  2339.                 }
  2340.             }
  2341.  
  2342.             if (act_info->di_taken || (!always_keys && (act_info->di_flag!=WINDOW || menu_dropped())))
  2343.                 events &= ~MU_KEYBD;
  2344.         }
  2345.  
  2346.         if (events)
  2347.         {
  2348.             act_info = get_info(&top);
  2349.         #ifndef SMALL_EGEM
  2350.             if (events & MU_M1)
  2351.             {
  2352.                 if (top)
  2353.                     mouse_cursor(act_info,&event);
  2354.                 else
  2355.                     event.ev_mflags &= ~MU_M1;
  2356.                 events &= ~MU_M1;
  2357.             }
  2358.         #endif
  2359.  
  2360.             if (events && do_func(act_info,top,events,&event))
  2361.                 return (W_ABANDON);
  2362.         }
  2363.     }
  2364. }
  2365.  
  2366. static DIAINFO *get_info(int *top)
  2367. {
  2368.     DIAINFO *winfo,*last;
  2369.  
  2370.     if (top)
  2371.         *top = FALSE;
  2372.  
  2373.     if (_dia_len>0)
  2374.     {
  2375.         if (top)
  2376.             *top = TRUE;
  2377.         return (_dia_list[_dia_len-1]);
  2378.     }
  2379.     else if (win_len>0)
  2380.     {
  2381.         int win_top;
  2382.  
  2383.         wind_update(BEG_UPDATE);
  2384.         win_top = _get_top();
  2385.         last = win_list[win_len-1];
  2386.         if (last->di_flag==WIN_MODAL || (!find_windial(win_top,&winfo) && !find_windial(_last_top,&winfo)))
  2387.             winfo = last;
  2388.  
  2389.         if (winfo->di_win->handle==win_top && !winfo->di_win->iconified)
  2390.             *top = TRUE;
  2391.         wind_update(END_UPDATE);
  2392.  
  2393.         return (winfo);
  2394.     }
  2395.     else
  2396.         return (NULL);
  2397. }
  2398.  
  2399. #ifndef SMALL_EGEM
  2400. static void mouse_cursor(DIAINFO *info,XEVENT *ev)
  2401. {
  2402.     reg GRECT area;
  2403.     reg OBJECT *tree=info->di_tree,*ob_ptr;
  2404.     reg int edit=FALSE,obj,x=ev->ev_mmox,y=ev->ev_mmoy;
  2405.  
  2406.     area = info->di_edit;
  2407.     area.g_x += tree->ob_x;
  2408.     area.g_y += tree->ob_y;
  2409.  
  2410.     if (rc_inside(x,y,&area) && (obj=objc_find(tree,ROOT,MAX_DEPTH,x,y))>=0)
  2411.     {
  2412.         ob_ptr = &tree[obj];
  2413.  
  2414.         ev->ev_mm1flags = 1;
  2415.         if ((ob_ptr->ob_flags & EDITABLE) && !(ob_ptr->ob_state & DISABLED))
  2416.         {
  2417.             EDINFO ed;
  2418.  
  2419.             edit = TRUE;
  2420.             _edit_get_info(tree,obj,0,&ed);
  2421.             if (rc_inside(x,y,(GRECT *) &ed.edit_x))
  2422.             {
  2423.                 if (mouse_flag!=TRUE)
  2424.                 {
  2425.                     MouseCursor();
  2426.                     mouse_flag = TRUE;
  2427.                 }
  2428.  
  2429.                 ev->ev_mm1x = ed.edit_x;
  2430.                 ev->ev_mm1y = ed.edit_y;
  2431.                 ev->ev_mm1width = ed.edit_w;
  2432.                 ev->ev_mm1height = ed.edit_h;
  2433.                 return;
  2434.             }
  2435.         }
  2436.  
  2437.         if (!edit && ob_ptr->ob_head<0)
  2438.         {
  2439.             objc_offset(tree,obj,&ev->ev_mm1x,&ev->ev_mm1y);
  2440.             ev->ev_mm1width = ob_ptr->ob_width;
  2441.             ev->ev_mm1height = ob_ptr->ob_height;
  2442.         }
  2443.         else
  2444.         {
  2445.             ev->ev_mm1x = x;
  2446.             ev->ev_mm1y = y;
  2447.             ev->ev_mm1width = ev->ev_mm1height = 1;
  2448.         }
  2449.     }
  2450.     else
  2451.     {
  2452.         ev->ev_mm1flags = 0;
  2453.         *(GRECT *) &ev->ev_mm1x = area;
  2454.     }
  2455.  
  2456.     if (mouse_flag!=FALSE)
  2457.     {
  2458.         MouseArrow();
  2459.         mouse_flag = FALSE;
  2460.     }
  2461. }
  2462. #endif
  2463.  
  2464. static int klickobj(DIAINFO *info,XEVENT *event,int *obj,boolean top)
  2465. {
  2466.     reg SLINFO **sl_list = (SLINFO **) info->di_slider,*slider;
  2467.     reg int ob,dummy,ind=FALSE;
  2468.     reg OBJECT *tree = info->di_tree,*ob_ptr;
  2469.  
  2470.     if (top || _back_win || (event->ev_mmobutton & 3)!=2)
  2471.     {
  2472.         if ((ob = objc_find(tree,ROOT,MAX_DEPTH,event->ev_mmox,event->ev_mmoy))>=0)
  2473.         {
  2474.             if (event->ev_mmobutton & 2)
  2475.             {
  2476.                 event->ev_mbreturn = (event->ev_mmobutton & 1) ? 1 : 2;
  2477.                 event->ev_mmobutton = 1;
  2478.             }
  2479.  
  2480.             ob_ptr = &tree[ob];
  2481.             if (sl_list!=NULL && !(ob_ptr->ob_state & DISABLED))
  2482.             {
  2483.                 while ((slider=*sl_list++)!=NULL)
  2484.                 {
  2485.                     if (ob==slider->sl_dec || ob==slider->sl_inc ||
  2486.                         ob==slider->sl_parent || ob==slider->sl_slider)
  2487.                     {
  2488.                         dummy = slider->sl_pos;
  2489.                         graf_rt_slidebox(slider,ob,event->ev_mbreturn!=1);
  2490.                         if (dummy!=slider->sl_pos)
  2491.                             _send_msg(info,slider->sl_slider,OBJC_CHANGED,0,0);
  2492.                         return (TRUE);
  2493.                     }
  2494.                 }
  2495.             }
  2496.  
  2497.             if (!(ob_ptr->ob_flags & (SELECTABLE|EDITABLE|EXIT|TOUCHEXIT)))
  2498.             {
  2499.                 if (!(ob_ptr->ob_state & DISABLED) && (dummy = is_rb_chk(tree,ob))>=0)
  2500.                 {
  2501.                     ob = dummy;
  2502.                     ind = TRUE;
  2503.                 }
  2504.                 else if (info->di_fly && _nonsel_fly)
  2505.                 {
  2506.                     Event_Timer(50,0);
  2507.                     if (_mouse_but() & 1)
  2508.                     {
  2509.                         do_jump_fly(info,FAIL,FAIL);
  2510.                         return(TRUE);
  2511.                     }
  2512.                 }
  2513.             }
  2514.  
  2515.             dummy = objekt_handler(info,ob,event->ev_mbreturn,event->ev_mmox,event->ev_mmoy,ind);
  2516.             if (dummy && dummy!=FAIL)
  2517.             {
  2518.                 *obj = dummy;
  2519.                 return(FALSE);
  2520.             }
  2521.         }
  2522.         else if (info->di_fly)
  2523.         {
  2524.             do_jump_fly(info,event->ev_mmox,event->ev_mmoy);
  2525.         #ifndef SMALL_EGEM
  2526.             mouse_cursor(info,event);
  2527.         #endif
  2528.             _no_click();
  2529.         }
  2530.         else
  2531.             return(FAIL);
  2532.  
  2533.         return(TRUE);
  2534.     }
  2535.  
  2536.     return(FAIL);
  2537. }
  2538.  
  2539. void _send_msg(void *info, int id, int msg_id,int msg6,int msg7)
  2540. {
  2541.     XEVENT event;
  2542.     reg int *msg = event.ev_mmgpbuf;
  2543.  
  2544.     *msg++ = msg_id;
  2545.     *msg++ = ap_id;
  2546.     *msg++ = 0;
  2547.     *msg++ = id;
  2548.     *((long *) msg)++ = (long) info;
  2549.     *msg++ = msg6;
  2550.     *msg++ = msg7;
  2551.     _call_event_handler(MU_MESAG,&event,FALSE);
  2552. }
  2553.  
  2554. static int key_handler(DIAINFO *info,int state,int scan,XEVENT *event)
  2555. {
  2556.     SLINFO **sl_list = (SLINFO **) info->di_slider,*slider;
  2557.     reg SLKEY *sl_keys;
  2558.     reg OBJECT *tree = info->di_tree;
  2559.     reg int sn=(int) (((unsigned) scan)>>8),obj,hot,shft;
  2560.     int ascii = scan_2_ascii(scan,state),cnt;
  2561. #ifndef SMALL_EGEM
  2562.     int edited;
  2563. #endif
  2564.  
  2565.     shft = (state & (K_RSHIFT|K_LSHIFT)) ? TRUE : FALSE;
  2566.     hot = shft ? 6 : 4;
  2567.  
  2568.     if (sl_list!=NULL)
  2569.         while ((slider=*sl_list++)!=NULL)
  2570.             if ((sl_keys=slider->sl_keys)!=NULL)
  2571.                 for (cnt=slider->sl_keys_cnt;--cnt>=0;sl_keys++)
  2572.                     if (((state^sl_keys->state) & (K_ALT|K_CTRL))==0)
  2573.                     {
  2574.                         if (sl_keys->state & (K_RSHIFT|K_LSHIFT))
  2575.                         {
  2576.                             if ((shft) && ((sl_keys->scan>>8)==sn || (ascii && (char) sl_keys->scan==ascii)))
  2577.                             {
  2578.                                 info->di_taken = TRUE;
  2579.                                 hot = slider->sl_pos;
  2580.                                 graf_rt_slidebox(slider,sl_keys->cmd,FALSE);
  2581.                                 if (hot!=slider->sl_pos)
  2582.                                     _send_msg(info,slider->sl_slider,OBJC_CHANGED,0,0);
  2583.                                 return (FAIL);
  2584.                             }
  2585.                         }
  2586.                         else if ((!shft) && ((sl_keys->scan>>8)==sn || (ascii && (char) sl_keys->scan==ascii)))
  2587.                         {
  2588.                             info->di_taken = TRUE;
  2589.                             graf_rt_slidebox(slider,sl_keys->cmd,FALSE);
  2590.                             return (FAIL);
  2591.                         }
  2592.                     }
  2593.  
  2594.     if (!state)
  2595.     {
  2596.         obj = FAIL;
  2597.  
  2598.         switch (sn)
  2599.         {
  2600.         case SCANRET:
  2601.         #ifdef SMALL_EGEM
  2602.             obj = info->di_default;
  2603.         #else
  2604.             if (return_default==TRUE || info->di_ed_obj<0)
  2605.                 obj = info->di_default;
  2606.  
  2607.             if (obj<=0 && info->di_ed_obj>0)
  2608.             {
  2609.                 obj = info->di_default;
  2610.                 if (_next_edit(info,(return_default==FALSE || obj<=0) ? TRUE : FALSE))
  2611.                 {
  2612.                     info->di_taken = TRUE;
  2613.                     return (FAIL);
  2614.                 }
  2615.             }
  2616.         #endif
  2617.             break;
  2618.         case SCANENTER:
  2619.         #ifndef SMALL_EGEM
  2620.             if (info->di_ed_obj<0)
  2621.         #endif
  2622.                 obj = info->di_default;
  2623.             break;
  2624.         case SCANHELP:
  2625.             obj = info->di_help;
  2626.             break;
  2627.         case SCANUNDO:
  2628.             obj = info->di_undo;
  2629.             break;
  2630.         }
  2631.  
  2632.         if (obj>0)
  2633.         {
  2634.             info->di_taken = TRUE;
  2635.             return(objekt_handler(info,obj,hot,FAIL,FAIL,FALSE));
  2636.         }
  2637.     }
  2638.  
  2639. #ifndef SMALL_EGEM
  2640.     if ((state & K_ALT) || (info->di_ed_obj<0 && !(state & K_CTRL)))
  2641. #else
  2642.     if (!(state & K_CTRL))
  2643. #endif
  2644.     {
  2645.         if ((obj = _is_hotkey(tree,ascii))>=0)
  2646.         {
  2647.             info->di_taken = TRUE;
  2648.  
  2649.             if (!_is_hidden(tree,obj))
  2650.             {
  2651.             #ifndef SMALL_EGEM
  2652.                 if (!(hot & 2) && (tree[obj].ob_flags & EDITABLE))
  2653.                     _set_cursor(info,obj,0x1000);
  2654.                 else
  2655.             #endif
  2656.                     return(objekt_handler(info,obj,hot,FAIL,FAIL,FALSE));
  2657.             }
  2658.  
  2659.             return(FAIL);
  2660.         }
  2661.     }
  2662.  
  2663. #ifndef SMALL_EGEM
  2664.     if (info->di_ed_obj>0)
  2665.     {
  2666.         obj = _objc_edit_handler(info,state,scan,event,&edited);
  2667.         if (edited && (info->di_ed_obj==info->di_inddef || (edited==FAIL && info->di_inddef>0)))
  2668.             test_inddefault(info);
  2669.         if (edited==TRUE)
  2670.             _send_msg(info,info->di_ed_obj,OBJC_EDITED,0,0);
  2671.     }
  2672. #endif
  2673.  
  2674.     return (obj);
  2675. }
  2676.  
  2677. static int is_rb_chk(reg OBJECT *tree,reg int obj)
  2678. {
  2679.     reg int index = 0;
  2680.  
  2681.     for (;;)
  2682.     {
  2683.         if (tree->ob_next==obj)
  2684.         {
  2685.             switch (tree->ob_type & G_TYPE)
  2686.             {
  2687.             case G_CHK:
  2688.             case G_RB:
  2689.                 return(index);
  2690.             default:
  2691.                 return(FAIL);
  2692.             }
  2693.         }
  2694.  
  2695.         if (tree->ob_flags & LASTOB)
  2696.             return (FAIL);
  2697.  
  2698.         tree++;
  2699.         index++;
  2700.     }
  2701. }
  2702.  
  2703. boolean _is_hidden(OBJECT *tree,int index)
  2704. {
  2705.     reg OBJECT *obj = tree+index;
  2706.  
  2707.     if ((obj->ob_flags & HIDETREE) || ((obj->ob_flags & EDITABLE) && (obj->ob_state & DISABLED)))
  2708.         return(TRUE);
  2709.     else
  2710.     {
  2711.         reg int act;
  2712.  
  2713.         for (act=index;--act>=0;)
  2714.         {
  2715.             obj--;
  2716.             if (obj->ob_head<=index && obj->ob_tail>=index)
  2717.                 if (obj->ob_flags & HIDETREE)
  2718.                     return(TRUE);
  2719.                 else
  2720.                     index = act;
  2721.         }
  2722.  
  2723.         return(FALSE);
  2724.     }
  2725. }
  2726.  
  2727. int _is_hotkey(OBJECT *tree,int ascii)
  2728. {
  2729.     reg OBJECT *obj = tree;
  2730.     reg int hot,index = 0;
  2731.  
  2732.     do
  2733.     {
  2734.         obj++;index++;
  2735.         switch (obj->ob_type & G_TYPE)
  2736.         {
  2737.         case G_HOTKEY:
  2738.             if (*((unsigned char *) &obj->ob_state)==ascii)
  2739.                 return(ob_get_parent(tree,index));
  2740.             break;
  2741.         case G_CHK:
  2742.         case G_RB:
  2743.             if ((hot=_get_hotkey(tree,index))>0 && *((unsigned char *) &tree[hot].ob_state)==ascii)
  2744.                 return(index);
  2745.         }
  2746.     }
  2747.     while (!(obj->ob_flags & LASTOB));
  2748.  
  2749.     return(FAIL);
  2750. }
  2751.  
  2752. static int objekt_handler(DIAINFO *info,int obj,int hot,int x,int y,boolean ind)
  2753. {
  2754.     reg OBJECT *tree = info->di_tree,*obptr = tree+obj;
  2755.     reg int flags = obptr->ob_flags;
  2756.     reg int state = obptr->ob_state, old_state = state;
  2757.  
  2758. #ifndef SMALL_EGEM
  2759.     if (!(hot & 2) && (x!=FAIL) && (flags & EDITABLE))
  2760.     {
  2761.         int dummy;
  2762.  
  2763.         if (!(state & DISABLED))
  2764.         {
  2765.             GRECT *edit_box;
  2766.             EDINFO ed;
  2767.             reg char *edit,*p;
  2768.             reg int pos,index,len,old;
  2769.  
  2770.             edit = _edit_get_info(tree,obj,0,&ed);
  2771.             edit_box = (GRECT *) &ed.edit_x;
  2772.             edit_box->g_w += 2;
  2773.  
  2774.             if (rc_inside(x,y,edit_box))
  2775.             {
  2776.                 len = (int) strlen(edit);
  2777.                 old = -1;
  2778.  
  2779.                 pos = min((x-ed.edit_x)/ed.cw,len);
  2780.                 for (p=edit,index=pos;--index>=0;)
  2781.                     if (*p++!='_')
  2782.                         pos--;
  2783.  
  2784.                 if (pos!=old)
  2785.                     _set_cursor(info,obj,pos);
  2786.  
  2787.                 return(FALSE);
  2788.             }
  2789.         }
  2790.  
  2791.         if ((dummy=is_rb_chk(tree,obj))!=FAIL)
  2792.         {
  2793.             obj = dummy;
  2794.             obptr = tree+obj;
  2795.             flags = obptr->ob_flags;
  2796.             old_state = state = obptr->ob_state;
  2797.  
  2798.             if (state & DISABLED)
  2799.                 return(FAIL);
  2800.         }
  2801.         goto object_handle;
  2802.     }
  2803.     else
  2804. #endif
  2805.     if (!(state & DISABLED))
  2806.     {
  2807.     #ifndef SMALL_EGEM
  2808.         object_handle:
  2809.     #endif
  2810.         if ((obptr->ob_type & G_TYPE)==G_FLY || ((obptr->ob_type & G_TYPE)>>8)==USERFLY)
  2811.             do_jump_fly(info,FAIL,FAIL);
  2812.         else if (flags & (SELECTABLE|EXIT|TOUCHEXIT))
  2813.         {
  2814.             if (flags & SELECTABLE)
  2815.             {
  2816.                 if ((flags & RBUTTON) && (state & SELECTED))
  2817.                     _no_click();
  2818.                 else if (obptr->ob_spec.userblk==&checkblk && (flags & TOUCHEXIT))
  2819.                 {
  2820.                     state &= ~(CHECKED|SELECTED); 
  2821.                     if (old_state & SELECTED)
  2822.                         state |= CHECKED;
  2823.                     else if (!(old_state & CHECKED))
  2824.                         state |= SELECTED;
  2825.  
  2826.                     obptr->ob_state = state;
  2827.  
  2828.                     ob_draw(info,obj);
  2829.                     _no_click();
  2830.  
  2831.                     _send_msg(info,obj,OBJC_CHANGED,0,0);
  2832.                     return (FALSE);
  2833.                 }
  2834.                 else
  2835.                 {
  2836.                     state ^= SELECTED;
  2837.  
  2838.                     if ((hot & 4) || ind || (flags & (RBUTTON|TOUCHEXIT)))
  2839.                     {
  2840.                         ob_select(info,tree,obj,FLIP_STATE,TRUE);
  2841.  
  2842.                         if (flags & RBUTTON)
  2843.                         {
  2844.                             reg int act = obj,lst,new;
  2845.  
  2846.                             for(;;)
  2847.                             {
  2848.                                 lst = act;
  2849.                                 new = obptr->ob_next;
  2850.  
  2851.                                 for(;;)
  2852.                                 {
  2853.                                     act = new;
  2854.                                     obptr  = tree+act;
  2855.  
  2856.                                     if (obptr->ob_tail==lst)
  2857.                                     {
  2858.                                         new = obptr->ob_head;
  2859.                                         lst = act;
  2860.                                     }
  2861.                                     else
  2862.                                     {
  2863.                                         if (act==obj)
  2864.                                             goto do_exit;
  2865.  
  2866.                                         if ((obptr->ob_state & SELECTED) && (obptr->ob_flags & RBUTTON))
  2867.                                         {
  2868.                                             ob_select(info,tree,act,CLEAR_STATE,TRUE);
  2869.                                             goto do_exit;
  2870.                                         }
  2871.                                         else
  2872.                                             break;
  2873.                                     }
  2874.                                 }
  2875.                             }
  2876.                         }
  2877.  
  2878.                         do_exit:
  2879.                         if ((ind || (flags & RBUTTON)) && !(flags & TOUCHEXIT))
  2880.                             _no_click();
  2881.  
  2882.                         if ((flags & (EXIT|TOUCHEXIT))==0)
  2883.                             _send_msg(info,obj,OBJC_CHANGED,0,0);
  2884.                     }
  2885.                     else
  2886.                     {
  2887.                         XEVENT event;
  2888.                         int x,y,events;
  2889.  
  2890.                         _beg_ctrl();
  2891.  
  2892.                         memset(&event,0,sizeof(XEVENT));
  2893.                         event.ev_mflags = MU_BUTTON|MU_M1;
  2894.                         event.ev_mbclicks = 1;
  2895.                         event.ev_bmask = 3;
  2896.  
  2897.                         objc_offset(tree,obj,&event.ev_mm1x,&event.ev_mm1y);
  2898.                         event.ev_mm1width = obptr->ob_width;
  2899.                         event.ev_mm1height = obptr->ob_height;
  2900.  
  2901.                         _mouse_pos(&x,&y);
  2902.                         if (rc_inside(x,y,(GRECT *) &event.ev_mm1x))
  2903.                         {
  2904.                             event.ev_mm1flags = 1;
  2905.                             ob_select(info,tree,obj,FLIP_STATE,TRUE);
  2906.                         }
  2907.                         else
  2908.                             event.ev_mm1flags = 0;
  2909.  
  2910.                         do
  2911.                         {
  2912.                             _no_button++;
  2913.                             events = Event_Multi(&event);
  2914.                             _no_button--;
  2915.                             if (events & MU_M1)
  2916.                             {
  2917.                                 event.ev_mm1flags = 1 - event.ev_mm1flags;
  2918.                                 ob_select(info,tree,obj,FLIP_STATE,TRUE);
  2919.                             }
  2920.                         } while (!(events & MU_BUTTON));
  2921.  
  2922.                         _end_ctrl();
  2923.  
  2924.                         if (obptr->ob_state!=old_state)
  2925.                         {
  2926.                             if ((flags & (EXIT|TOUCHEXIT))==0)
  2927.                                 _send_msg(info,obj,OBJC_CHANGED,0,0);
  2928.                         }
  2929.                         else
  2930.                             return (FALSE);
  2931.                     }
  2932.                 }
  2933.             }
  2934.             else if (flags & EXIT)
  2935.                 _no_click();
  2936.  
  2937.             if (flags & (EXIT|TOUCHEXIT))
  2938.             {
  2939.                 if (hot & 2)
  2940.                     return(obj|0x8000);
  2941.                 else
  2942.                     return(obj);
  2943.             }
  2944.             else
  2945.                 return(FALSE);
  2946.         }
  2947.     }
  2948.  
  2949.     return(FAIL);
  2950. }
  2951.  
  2952. static void do_jump_fly(DIAINFO *info,int x,int y)
  2953. {
  2954.     RC_RECT dial;
  2955.     reg OBJECT *tree = info->di_tree;
  2956.     reg GRECT *area = &info->di_rc.area;
  2957.  
  2958.     _rc_sc_savetree(tree,&dial);
  2959.  
  2960. #ifndef SMALL_EGEM
  2961.     if (!dial.valid)
  2962.         _cursor_off(info);
  2963. #endif
  2964.  
  2965.     MouseOff();
  2966.     rc_sc_restore(area->g_x,area->g_y,&info->di_rc,FALSE);
  2967.     MouseOn();
  2968.  
  2969.     if (x<0)
  2970.     {
  2971.         MouseFlatHand();
  2972.         graf_dragbox(area->g_w,area->g_h,area->g_x,area->g_y,desk.g_x+1,desk.g_y+1,desk.g_w-2,desk.g_h-2,&tree->ob_x,&tree->ob_y);
  2973.         MouseArrow();
  2974.         tree->ob_x += 3;tree->ob_y += 3;
  2975.     }
  2976.     else
  2977.     {
  2978.         int ox = tree->ob_x,oy = tree->ob_y;
  2979.         tree->ob_x = x - (tree->ob_width>>1);
  2980.         tree->ob_y = y - (tree->ob_height>>1);
  2981.         graf_movebox(tree->ob_width,tree->ob_height,ox,oy,tree->ob_x,tree->ob_y);
  2982.     }
  2983.  
  2984.     dial_pos(tree,4,3);
  2985.  
  2986.     MouseOff();
  2987.     rc_sc_freshen(x=tree->ob_x-3,y=tree->ob_y-3,&info->di_rc);
  2988.     if (dial.valid)
  2989.         rc_sc_restore(x,y,&dial,TRUE);
  2990.     else
  2991.     {
  2992.         objc_draw(tree,ROOT,MAX_DEPTH,desk.g_x,desk.g_y,desk.g_w,desk.g_h);
  2993.     #ifndef SMALL_EGEM
  2994.         _set_cursor(info,FAIL,FAIL);
  2995.     #endif
  2996.     }
  2997.     MouseOn();
  2998. }
  2999.  
  3000. boolean open_rsc(char *rscname,char *m_entry,char *x_name,char *a_name,int av_msgs,int va_msgs,int xacc_msgs)
  3001. {
  3002.     if (init_gem(m_entry,x_name,a_name,av_msgs,va_msgs,xacc_msgs)==TRUE)
  3003.     {
  3004.         if (rsrc_load(rscname))
  3005.         {
  3006.             reg OBJECT *obj;
  3007.             reg int index;
  3008.             OBJECT *tree=NULL;
  3009.             RSHDR *rsc=*((RSHDR **) &GLOBAL[7]);
  3010.  
  3011.             index = rsc->rsh_ntree;
  3012.             while (--index>=0 && rsrc_gaddr(R_TREE,index,&tree) && tree!=NULL)
  3013.             {
  3014.                 for (obj=tree;;)
  3015.                 {
  3016.                     if (obj->ob_x==0 && obj->ob_width>max_w)
  3017.                         obj->ob_width = max_w;
  3018.                     if (obj->ob_flags & LASTOB)
  3019.                         break;
  3020.                     else
  3021.                         obj++;
  3022.                 }
  3023.  
  3024.                 tree = NULL;
  3025.             }
  3026.             return(TRUE);
  3027.         }
  3028.         else
  3029.         {
  3030.             exit_gem(FAIL);
  3031.             return(FAIL);
  3032.         }
  3033.     }
  3034.     else
  3035.         return(FALSE);
  3036. }
  3037.  
  3038. void close_rsc(int result)
  3039. {
  3040.     rsrc_free();
  3041.     exit_gem(result);
  3042. }
  3043.  
  3044. boolean open_work(int *handle,int *work_out)
  3045. {
  3046.     reg int i,work_in[11];
  3047.  
  3048.     *handle = grhandle;
  3049.     for (i = 0; i <= 9; work_in[i++] = 1);work_in[i] = 2;
  3050.     v_opnvwk(work_in, handle, work_out);
  3051.  
  3052.     return((*handle>0) ? TRUE : FALSE);
  3053. }
  3054.  
  3055. void close_work(int handle)
  3056. {
  3057.     v_clsvwk(handle);
  3058. }
  3059.  
  3060. int xdialog(OBJECT *tree,char *name,char *icon_name,OBJECT *icon,boolean center,boolean shrgrw,int mode)
  3061. {
  3062.     DIAINFO info;
  3063.     int exit;
  3064.  
  3065.     open_dialog(tree,&info,name,icon_name,icon,center,shrgrw,mode,0,NULL);
  3066.     exit = X_Form_Do(NULL);
  3067.     if (exit!=W_ABANDON && exit!=W_CLOSED)
  3068.     {
  3069.         exit &= 0x7fff;
  3070.         ob_undostate(tree,exit,SELECTED);
  3071.     }
  3072.     close_dialog(&info,shrgrw);
  3073.  
  3074.     return(exit);
  3075. }
  3076.  
  3077. int menu_install(OBJECT *tree,int show)
  3078. {
  3079.     if (tree!=NULL && menu_available)
  3080.     {
  3081.         if (show)
  3082.         {
  3083.             show = (menu_inst && !_app) ? 100 : 1;
  3084.             _menu = tree;
  3085.  
  3086.             _set_menu();
  3087.         }
  3088.         else
  3089.             _menu = NULL;
  3090.  
  3091.         if (menu_bar(tree,show))
  3092.             return (TRUE);
  3093.     }
  3094.  
  3095.     _menu = NULL;
  3096.     return (FALSE);
  3097. }
  3098.  
  3099. void menu_item_enable(int object,int enable)
  3100. {
  3101.     if (_menu)
  3102.         menu_ienable(_menu,object,(enable) ? 1 : 0);
  3103. }
  3104.  
  3105. void menu_select(int titel,int select)
  3106. {
  3107.     if (_menu)
  3108.         menu_tnormal(_menu,titel,(select) ? 0 : 1);
  3109. }
  3110.  
  3111. void menu_enable(boolean enable)
  3112. {
  3113.     if (_menu)
  3114.     {
  3115.         reg OBJECT *tree = _menu, *obj = _menu;
  3116.         reg int index = 0,title = 0,string = 1;
  3117.         reg int min_x = max_w,max_x = 0;
  3118.         int x,d,act;
  3119.  
  3120.         wind_update(BEG_UPDATE);
  3121.         if (menu_test && menu_bar(tree,-1)==ap_id)
  3122.             act = TRUE;
  3123.         else if (get_top_window()!=NULL)
  3124.             act = TRUE;
  3125.         else
  3126.             act = FALSE;
  3127.         menu_bar(tree,0);
  3128.  
  3129.         for (;;)
  3130.         {
  3131.             switch (obj->ob_type)
  3132.             {
  3133.             case G_TITLE:
  3134.                 objc_offset(tree,index,&x,&d);
  3135.                 x += obj->ob_width;
  3136.  
  3137.                 min_x = min(min_x,x);
  3138.                 max_x = max(max_x,x);
  3139.  
  3140.                 if (title)
  3141.                     menu_item_enable(index,enable);
  3142.                 else
  3143.                     title = 1;
  3144.                 break;
  3145.             case G_STRING:
  3146.                 if (string)
  3147.                 {
  3148.                     menu_item_enable(index,enable);
  3149.                     string = 0;
  3150.                 }
  3151.             }
  3152.  
  3153.             if (obj->ob_flags & LASTOB)
  3154.                 break;
  3155.             else
  3156.             {
  3157.                 obj++;
  3158.                 index++;
  3159.             }
  3160.         }
  3161.  
  3162.         objc_offset(tree,2,&x,&d);
  3163.         if (enable)
  3164.             tree[2].ob_width = max_x - x;
  3165.         else
  3166.             tree[2].ob_width = min_x - x;
  3167.  
  3168.         menu_bar(tree,(!act && menu_inst) ? 100 : 1);
  3169.         wind_update(END_UPDATE);
  3170.     }
  3171. }
  3172.  
  3173. boolean menu_dropped(void)
  3174. {
  3175.     reg OBJECT *obj = _menu;
  3176.  
  3177.     if (obj!=NULL)
  3178.         do
  3179.         {
  3180.             obj++;
  3181.             if (obj->ob_state & SELECTED)
  3182.                 return (TRUE);
  3183.         } while (!(obj->ob_flags & LASTOB));
  3184.  
  3185.     return (FALSE);
  3186. }
  3187.